【问题标题】:Mocking InputStreamReader with console input in Spock在 Spock 中使用控制台输入模拟 InputStreamReader
【发布时间】:2016-01-25 12:54:38
【问题描述】:

我有以下代码:

class MyWorker implements Runnable {
    MyReader reader
    Writer writer // java.io.Writer
    CommandFactory commandFactory

    @Inject
    MyWorker(MyReader reader, Writer writer, CommandFactory commandFactory) {
        super()
        this.reader = reader
        this.writer = writer
        this.commandFactory = commandFactory
    }

    @Override
    void run() {
        try {
            String line
            while ((line = reader.readLine()) != null) {
                // Commands have an execute method.
                commandFactory.createCommand(line).execute(writer)
                writer.flush()
            }
        } catch(InterruptedException ex) {
            log.warn("${this} interrupted with: ${ExceptionUtils.getStackTrace(ex)}")
        }
    }
}

我正在尝试编写一个 Spock Specification 来验证按下换行符(Enter Key)时发生的几件事:

  1. 一个command被执行
  2. Writerflush()ed

这是我目前所拥有的:

class MyWorkerSpec extends Specification {
    def "when enter key is pressed then a command is selected and executed and the writer is flushed"() {
        given: "a running fixture with some mock dependencies"
        MyReader reader = Mock()
        Writer writer = Mock()
        Command command = Mock()
        CommandFactory commandFactory = Mock()
        commandFactory.createCommand(Spock.ANY) << command      // FIXME #1: Have it always return mock cmd

        MyWorker worker = new MyWorker(reader, writer, commandSelector)
        worker.run()

        when: "the enter key is pressed"
        // reader.input gives you a java.io.InputStream
        reader.input.write << '\n'                              // FIXME #2: Send it a newline

        then: "a command is executed"
        1 * command.execute(Spock.ANY)                          // FIXME #4: How to specify "any"

        and: "a writer is flushed"
        1 * writer.flush()                                      // FIXME #5 (how to guarante ordering of cmd -> flush)
    }
}

如您所见,在给定“任何”输入的情况下,我很难连接模拟 CommandFactory 以返回模拟 Command。我也很难明确地发送模拟 readerInpuStream 换行符(以触发场景)。我也不确定测试方法是否强制排序(首先执行命令,然后刷新writer)。

关于我要去哪里出错的任何想法?

【问题讨论】:

    标签: unit-testing groovy mocking spock


    【解决方案1】:

    您应该使用&gt;&gt; 运算符而不是&lt;&lt;。此外,在 Spock 中,any 是 _ 字符。

    要创建一个总是返回命令的模拟,请使用:

    def commandFactory = Mock(CommandFactory) {
      createCommand(_) >> command
    }
    

    应该模拟您的 MyReader 以返回另一个模拟的 InputStream :

    def readerStream = Mock(InputStream) {
      write() >> '\n'
    }
    def myReader = Mock(MyReader) {
      input >> readerStream
    }
    

    最后,要对交互进行排序,您应该使用多个 'then' 块:

    then: "a command is executed"
      1 * command.execute(_)
    
    then: "a writer is flushed"
      1 * writer.flush()
    

    【讨论】:

      猜你喜欢
      • 2020-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多