Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Loops Mockito mock具有无限循环的方法_Loops_Testing_Mocking_Mockito_Infinite - Fatal编程技术网

Loops Mockito mock具有无限循环的方法

Loops Mockito mock具有无限循环的方法,loops,testing,mocking,mockito,infinite,Loops,Testing,Mocking,Mockito,Infinite,我有一个方法如下 public class ClientClass { public void clientMethod() { while(true){ doSomethings..... } } } 我正在尝试使用mockito进行测试。我能够调用clientMethod,但由于clientMethod中有一段时间(true),因此调用永远不会返回,我也永远不会到达我的断言语句,而断言语句(当然)发生在clientMet

我有一个方法如下

public class ClientClass {

    public void clientMethod() {
        while(true){
           doSomethings.....
       }
    }
}
我正在尝试使用mockito进行测试。我能够调用clientMethod,但由于clientMethod中有一段时间(true),因此调用永远不会返回,我也永远不会到达我的断言语句,而断言语句(当然)发生在clientMethod()调用之后。
在我的测试用例中进行一次循环迭代后,有没有办法停止循环?

从技术上讲,如果不从内部抛出异常,就无法在测试中中断无限循环。如果循环中存在可以模拟的内容,那么它可能会为您生成一个异常

当您发现自己处于这样的情况时,当测试需要尴尬的变通方法时,是时候停下来思考一下设计了。不可测试的代码通常是不可维护的,并且不是很自解释的。所以我的建议是去掉无限循环,引入一个合适的循环条件。毕竟,没有一个应用程序会永远存在

如果您仍然相信无止境循环是最好的方法,那么您可以执行一个轻微的分解,使事情更易于测试:

public class ClientClass {

  // call me in production code
  public void clientMethod() {
    while(true){
        doSomethings();
    }
  }

  // call me in tests
  void doSomethings(){
    // loop logic
  }
}

这让我有点沮丧。。。因为我喜欢用控制台处理程序启动最复杂的GUI应用程序

我在这里使用的语言是Groovy,它是Java的一种极好的扩展,可以和普通的旧Java混合在一起

class ConsoleHandler {

    def loopCount = 0
    def maxLoopCount = 100000

    void loop() {
        while( ! endConditionMet() ){
            // ... do something
        }
    }

    boolean endConditionMet() {
        loopCount++
        loopCount > maxLoopCount // NB no "return" needed!
    }

    static void main( args ) {
        new ConsoleHandler().loop()
    }
}
。。。在测试类中(也在Groovy中),您可以

import org.junit.contrib.java.lang.system.SystemOutRule
import org.junit.contrib.java.lang.system.
    TextFromStandardInputStream.emptyStandardInputStream
import static org.assertj.core.api.Assertions.assertThat
import org.junit.Rule
import static org.mockito.Mockito.*

class XXTests {
    @Rule
    public SystemOutRule systemOutRule = new SystemOutRule().enableLog()
    @Rule
    public TextFromStandardInputStream systemInMock = emptyStandardInputStream()
    ConsoleHandler spyConsoleHandler = spy(new ConsoleHandler())

    @Test
    void readInShouldFollowedByAnother()  {
        spyConsoleHandler.setMaxLoopCount 10
        systemInMock.provideLines( 'blah', 'boggle')
        spyConsoleHandler.loop()
        assertThat( systemOutRule.getLog() ).containsIgnoringCase( 'blah' )
        assertThat( systemOutRule.getLog() ).containsIgnoringCase( 'boggle' )
这里发生的一件美妙的事情是,只要声明
maxLoopCount
,该语言就会自动创建两个方法:
getMaxLoopCount
setMaxLoopCount
(您甚至不必为括号而烦恼)

当然,下一个测试将是“如果用户输入Q,则必须退出循环”或其他任何测试。。。但是关于TDD的要点是,您希望它在一开始就失败


如果必须的话,可以使用普通的旧Java复制上述内容:当然,您必须创建自己的
setXXX
方法。

我陷入了这个困境,因为我错误地从方法内部调用了相同的方法

public OrderEntity createNewOrder(NewDepositRequest request, String userId) {
    return createNewOrder(request, userId);
}

当代码在生产环境中运行时,程序将如何从循环中退出?你能模拟同样的情况吗?