问题
Here is my main class:
@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)}")
}
}
}
Here is my attempt at a Spock Specification
for that class:
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(_)
}
}
Essentially, I want to confirm that when the run()
method is invoked, that the commandSelector#select()
method is invoked with any argument.
When I run this I get:
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)
Line 33 of ConsoleReadyWorker
is the call to commandSelector.select()
that lives inside the while
loop:
commandSelector.select(line).execute(writer)
Any ideas as to why?!? As you can see, I've wired commandSelector#select()
mock to return the RemoteCommand
mock, so it should never be null...ideas?
回答1:
Try:
then: "a command is executed"
1 * commandSelector.select(_) >> command
instead of:
commandSelector.select(_) >> command
Please have a look at the docs. When you both mock and verify, then
block should be used.
EDIT
This is spock related error you're getting, trust me. Have a look at the runnable script below (can be run using groovy console):
@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()
}
}
It fails since select
is invoked twice, but does not fail with NPE. To fix it add the following line:
reader.readLine() >>> ['\n', null]
来源:https://stackoverflow.com/questions/35059223/spock-mocks-showing-up-as-nulls