如何仅对函数的部分进行模拟

huangapple go评论62阅读模式
英文:

How to mock only a part of a function

问题

我正在构建一个自动游戏客户端,该客户端应在4连棋游戏中对我进行移动。为了进行移动,它应选择一列,并通过调用move()函数将所选列发送到我的服务器。

public class AutomaticGameClient {

  private String userName;
  private String userPassword;

  public AutomaticGameClient(String userName, String userPassword) {
    this.userName = userName;
    this.userPassword = userPassword;
  }

  public int makeMove() {
      columnNo = 0;
      move(columnNo);
      return columnNo;
  }

}

目前,它总是通过在第一行中进行下一步移动 (columnNo = 0)。这是有效的。
现在我必须测试该函数,但我不想测试move()部分。我只想断言它是否返回了0:

@Test
public void whenMakeMove_columnNoIsZero() {
    AutomaticGameClient agcY = new AutomaticGameClient("Georg1", "geheim1");
    int rowMoved = agcY.makeMove();
    assertEquals(rowMoved, 0);
}

当我运行此测试时,我会得到org.java_websocket.exceptions.WebsocketNotConnectedException,因为move(columnNo)正在尝试启动到我的套接字的连接。那么,有没有办法跳过要测试的函数的这部分内容呢?

英文:

I'm building an automatic game client that is supposed to make moves against me in a 4-Wins-Game. For making a move it should chose a column and send that chosen column by calling the move() function to my server.

public class AutomaticGameClient {

  private String userName;      
  private String userPassword;

  public AutomaticGameClient(String userName, String userPassword) {
    this.userName = userName;
    this.userPassword = userPassword;
  }

  public int makeMove() {
      columnNo = 0;
      move(columnNo);
      return columnNo;
  }

}

Right now it always simply moves by making the next move in the first row (columnNo = 0). This works.
Now I have to test that function, but I don't want to test the move() part. I only want to assert, that it's returning 0:

  @Test
public void whenMakeMove_columnNoIsZero() {
    AutomaticGameClient agcY = new AutomaticGameClient("Georg1", "geheim1");
    int rowMoved = agcY.makeMove();
    assertEquals(rowMoved, 0);

}

When I run this test, I get org.java_websocket.exceptions.WebsocketNotConnectedException, because move(columnNo) is trying to start a connection to my socket. So is there a way to skip this part of the function under test?

答案1

得分: 2

"那么有没有办法跳过测试函数的这一部分呢?" - 是的。可以创建被测单元的部分模拟/间谍对象,然后模拟 move(...) 方法。更多细节请参考Victor Grazi的这篇帖子及其答案

然而,在这个具体的情况下,更清晰的解决方案是将与 socket 相关的代码移动到一个独立的服务中。一个单元应该作为一个单元进行测试,因此我们应该很少使用模拟,只有在没有其他可能性的情况下才使用。但是,这是单元之间的边界,因此为了更好地进行测试,应该将套接字通信移动到一个单独的单元中。请注意,我并不是说每个类都是一个单元。一个单元可以由多个类组成。但一个类不应该由多个单元组成,因为这样我们就不得不使用部分模拟来测试被测单元。在我看来,模拟被测单元始终是一个警告信号。

英文:

"So is there a way to skip this part of the function under test?" - Yes. One could create a partial mock/spy of the unit under test and then mock the move(...)-method. For more details please refer to this posts by Victor Grazi and its answers.

In this concrete situation, however, the cleaner solution would be to move socket-related code to a separate service. A unit should be tested as a unit and thus we should use mocks seldomly and only if no other possibility exists. This, however, is a boundary between units, thus socket-communication should be moved in a separate unit for better testability. Please notice that I do not say that each class is a unit. A unit can be composed of multiple classes. But one class should not be composed of multiple units since we then have to resort to solutions like partial mocks for the unit under test. In my opinion, mocking the unit under test is always a red flag.

huangapple
  • 本文由 发表于 2020年9月22日 21:11:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/64010497.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定