这是我的主要课程:
@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 ...想法?
答案 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]