Spock嘲笑显示为空

时间:2016-01-28 10:44:30

标签: unit-testing groovy spock

这是我的主要课程:

@Slf4j
class ConsoleReaderWorker implements Runnable {
    ConsoleReader reader
    Writer writer
    RemoteCommandSelector commandSelector

    @Inject
    ConsoleReaderWorker(ConsoleReader reader, Writer writer, RemoteCommandSelector commandSelector) {
        super()
        this.reader = reader
        this.writer = writer
        this.commandSelector = commandSelector
    }

    @Override
    void run() {
        try {
            String line
            while ((line = reader.readLine()) != null) {
                commandSelector.select(line).execute(writer)
                writer.flush()
            }
        } catch(InterruptedException ex) {
            log.warn("${this} interrupted with: ${ExceptionUtils.getStackTrace(ex)}")
        }
    }
}

以下是我对该类的Spock Specification的尝试:

class ConsoleReaderWorkerSpec 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"
        ConsoleReader reader = Mock(ConsoleReader)
        Writer writer = Mock(Writer)
        RemoteCommand command = Mock(RemoteCommand)
        RemoteCommandSelector commandSelector = Mock(RemoteCommandSelector)

        reader.readLine() >> '\n'
        commandSelector.select(_) >> command

        ConsoleReaderWorker worker = new ConsoleReaderWorker(reader, writer, commandSelector)

        when: "the enter key is pressed"
        worker.run()

        then: "a command is executed"
        1 * commandSelector.select(_)
    }
}

基本上,我想确认在调用run()方法时,使用任何参数调用commandSelector#select()方法。

当我跑步时,我得到:

java.lang.NullPointerException: Cannot invoke method execute() on null object
    at com.nocbots.nbsvc.remote.cli.jline.ConsoleReaderWorker.run(ConsoleReaderWorker.groovy:33)
    at com.nocbots.nbsvc.remote.cli.jline.ConsoleReaderWorkerSpec.when enter key is pressed then a command is selected and executed and the writer is flushed(ConsoleReaderWorkerSpec.groovy:25)

ConsoleReadyWorker第33行是对commandSelector.select()循环内while的调用:

commandSelector.select(line).execute(writer)

关于为什么的任何想法?!?正如你所看到的,我已经连接了commandSelector#select() mock来返回RemoteCommand模拟,所以它永远不应该是null ...想法?

1 个答案:

答案 0 :(得分:1)

尝试:

then: "a command is executed"
1 * commandSelector.select(_) >> command

而不是:

commandSelector.select(_) >> command

请查看docs。当您同时进行模拟和验证时,应使用then块。

修改

这是与你有关的spock相关错误,相信我。看看下面的runnable脚本(可以使用groovy控制台运行):

@Grab('org.spockframework:spock-core:1.0-groovy-2.4')
@Grab('cglib:cglib-nodep:3.1')

import spock.lang.*

class ConsoleReaderWorkerSpec 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"
        ConsoleReader reader = Mock(ConsoleReader)
        Writer writer = Mock(Writer)
        RemoteCommand command = Mock(RemoteCommand)
        RemoteCommandSelector commandSelector = Mock(RemoteCommandSelector)

        reader.readLine() >> '\n'

        ConsoleReaderWorker worker = new ConsoleReaderWorker(reader, writer, commandSelector)

        when: "the enter key is pressed"
        worker.run()

        then: "a command is executed"
        1 * commandSelector.select(_) >> command
    }
}

class ConsoleReaderWorker implements Runnable {

    ConsoleReader reader
    Writer writer
    RemoteCommandSelector commandSelector

    ConsoleReaderWorker(ConsoleReader reader, Writer writer, RemoteCommandSelector commandSelector) {
        this.reader = reader
        this.writer = writer
        this.commandSelector = commandSelector
    }

    @Override
    void run() {
        try {
            String line
            while ((line = reader.readLine()) != null) {
                commandSelector.select(line).execute(writer)
                writer.flush()
            }
        } catch(InterruptedException ex) {
            log.warn("${this} interrupted with: ${ExceptionUtils.getStackTrace(ex)}")
        }
    }
}
class Writer {
   void flush() {}
}
class RemoteCommand {
   void execute(Writer w) {

   }
}
class ConsoleReader {
   String readLine() {
      ''
   }
}
class RemoteCommandSelector {
   RemoteCommand select(o) {
      new RemoteCommand()
   }
}

它失败,因为select被调用了两次,但是NPE没有失败。要修复它,请添加以下行:

reader.readLine() >>> ['\n', null]