【问题标题】:Asserting complex spock interaction断言复杂的 spock 交互
【发布时间】:2015-03-18 09:32:10
【问题描述】:

一直在努力让这个 spock 测试正常工作。

被测代码:

import org.slf4j.Logger
import org.slf4j.LoggerFactory

public class UserConsole {
    private static final Logger LOG = LoggerFactory.getLogger(UserConsole.class);

    public boolean getConfirmationFromUser() {
        writeLine("USER RESPONSE REQUIRED: yes/no");
        while(true) {
            final String userResponse = readLine();
            if(userResponse.trim().equalsIgnoreCase("yes")){
                return true;
            } else if(userResponse.trim().equalsIgnoreCase("no")){
                return false;
            }
            writeLine("Invalid input received '" + userResponse + "'.  Legal values are: 'yes' or 'no'");
        }
    }

    public String readLine() {
        return System.console().readLine();
    }

    public void writeLine(final String text){
        LOG.info(text);
    }
}

还有我的测试代码:

import spock.lang.Specification

class UserConsoleTest extends Specification {
    def "test getConfirmationFromUser"() {
        given:
        final UserConsole userConsole = Spy(UserConsole)

        when:
        boolean result = userConsole.getConfirmationFromUser();

        then:
        1 * userConsole.writeLine("USER RESPONSE REQUIRED: yes/no")
        1 * userConsole.readLine() >> "blah!"
        1 * userConsole.writeLine("Invalid input received 'blah!'.  Legal values are: 'yes' or 'no'")
        1 * userConsole.readLine() >> "still blah!"
        1 * userConsole.writeLine("Invalid input received 'still blah!'.  Legal values are: 'yes' or 'no'")
        1 * userConsole.readLine() >> "yes"
        assert result == true
    }
}

测试的想法是向控制台提供两个错误的响应(“blah!”和“still blah!”,然后是一个有效的响应(“yes”)

但是我无法让 spock 验证交互。我经常看到这样的断言失败:

Too few invocations for:

1 * userConsole.writeLine("Invalid input received 'blah!'.  Legal values are: 'yes' or 'no'")   (0 invocations)

Unmatched invocations (ordered by similarity):

3 * userConsole.invokeMethod('readLine', [])
1 * userConsole.getConfirmationFromUser()

Too few invocations for:

1 * userConsole.writeLine("Invalid input received 'still blah!'.  Legal values are: 'yes' or 'no'")   (0 invocations)

Unmatched invocations (ordered by similarity):

3 * userConsole.invokeMethod('readLine', [])
1 * userConsole.getConfirmationFromUser()


    at org.spockframework.mock.runtime.InteractionScope.verifyInteractions(InteractionScope.java:78)
    at org.spockframework.mock.runtime.MockController.leaveScope(MockController.java:76)
    at com.anz.axle.tooling.installer.UserConsoleTest.test GetConfirmationFromUser user initially enters invalid value(UserConsoleTest.groovy:39)

任何帮助将不胜感激。

【问题讨论】:

    标签: unit-testing spock


    【解决方案1】:

    如果您想订购交互模拟,那么您实际上需要单独的 then 块。如果它们都在同一个块中,则没有断言顺序。

    import spock.lang.Specification
    
    class UserConsoleTest extends Specification {
      def "test getConfirmationFromUser"() {
        given:
          final UserConsole userConsole = Spy(UserConsole)
    
        when:
          boolean result = userConsole.getConfirmationFromUser();
    
        then:
          1 * userConsole.writeLine("USER RESPONSE REQUIRED: yes/no")
          1 * userConsole.readLine() >> "blah!"
        then:
          1 * userConsole.writeLine("Invalid input received 'blah!'.  Legal values are: 'yes' or 'no'")
          1 * userConsole.readLine() >> "still blah!"
        then:
          1 * userConsole.writeLine("Invalid input received 'still blah!'.  Legal values are: 'yes' or 'no'")
          1 * userConsole.readLine() >> "yes"
        then:
          assert result == true
      }
    }
    

    【讨论】:

      【解决方案2】:

      我认为您没有在应该使用的地方使用 writeLine 方法(根据您的测试):

      import org.slf4j.Logger
      import org.slf4j.LoggerFactory
      
      public class UserConsole {
          private static final Logger LOG = LoggerFactory.getLogger(UserConsole.class);
      
          public boolean getConfirmationFromUser() {
              writeLine("USER RESPONSE REQUIRED: yes/no");
              while(true) {
                  final String userResponse = readLine();
                  if(userResponse.trim().equalsIgnoreCase("yes")){
                      return true;
                  } else if(userResponse.trim().equalsIgnoreCase("no")){
                      return false;
                  }
                  writeLine("Invalid input received '" + userResponse + "'.  Legal values are: 'yes' or 'no'");
              }
          }
      
          public String readLine() {
              return System.console().readLine();
          }
      
          public void writeLine(final String text){
              LOG.info(text);
          }
      }
      

      让我知道这是否成功。

      【讨论】:

      • 是的,你完全正确。非常感谢,这是一个愚蠢的错误。我将用你的修复来清理这个问题。上面的另一个答案实际上确定了 spock 的外观,因此将清理问题,并留下另一个答案以帮助其他人解决类似的 spock 问题。
      猜你喜欢
      • 1970-01-01
      • 2015-04-11
      • 1970-01-01
      • 2014-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-06
      • 1970-01-01
      相关资源
      最近更新 更多