lundi 25 janvier 2016

Mocking InputStreamReader with console input in Spock

I have the following code:

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)}")
        }
    }
}

I am trying to write a Spock Specification that verifies several things happen when a newline (Enter Key) is pressed:

  1. A command is executed
  2. A Writer is flush()ed

Here's what I have so far:

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)
    }
}

As you can see, I'm having a tough time wiring up the mock CommandFactory to return the mock Command given "any" input. I'm also having a tough time explicitly sending the mock reader's InpuStream a newline (so as to trigger the scenario). I'm also not sure if the test method enforces ordering (first execute the command, then flush the writer).

Any ideas as to where I'm going awry?

Aucun commentaire:

Enregistrer un commentaire