0

This post is similar to: this

I have a console app that expects both user input and has responsive user output. I am writing some unit tests for it to make sure that the code works properly. I need to be able to make sure that the output and input for it are what I expect them to be.

Essentially, I have a main method being tested that asks for a file or input. In my test, I use System.setOut and System.setIn to set those to context.mock versions of PrintStream and InputStream objects respectively. I don't care about what System.out.println calls get made until I have to test the actual processing of the program data, when it outputs its results to the console. So to summarize:

Here's my source being tested (something close, I trimmed much out): http://ideone.com/rptC0

Here's what I have in my mocking procedure: http://ideone.com/VkvqM

And here's the exception that I'm getting: ideone.com/OEOS8

As you can clearly see in my expectations, I'm explicitly saying that I was planning to print the exact same string out, and I specified that in my expectations. But the exception says that it was unexpected. I don't understand...

Community
  • 1
  • 1
Adam Miller
  • 1,756
  • 1
  • 25
  • 44
  • If you're going to post linked code, a [SSCCE](http://sscce.org) will probably get you better answers quicker... – DNA Apr 21 '12 at 20:13
  • you're right, sorry, repost with SSCCE below. – Adam Miller Apr 21 '12 at 21:25
  • Unfortunately, that's not self-contained (several other classes are needed such as `Word` and `WordFrequency`) nor correct - `main` doesn't compile because it uses type 'bool' and calls an undefined method `inputReadFailure` – DNA Apr 21 '12 at 21:45
  • Oh crap... err. I wasn't finished editing the link when you took it. Hold on, I'll fix those, I just finished fixing them... – Adam Miller Apr 21 '12 at 21:52
  • OK, I have edited my copy to get it working and I think I see the problem - see my comment below (will also edit the answer). – DNA Apr 21 '12 at 21:55

1 Answers1

0

JMock expects you to declare the Expectations using context.checking() then call the code under test, then call context.assertIsSatisfied() (although sometimes the last step is done implicitly if using an appropriate test runner).

You seem to be immediately calling context.assertIsSatisfied() before running any code.

Also, the code you posted uses the variable mn which does not appear to be defined - is that actually the code you are running? Or should that variable be mockIn instead?

Updated: OK, the problem is probably that you are trying to mock a static method - JMock doesn't support this - see jmock mocking a static method . See particularly the answer from Steve Freeman, who is one of the JMock authors.

Updated 2: I would try something like this, setting an expectation in the @Before setup:

@Before
public void setMinimalMockingExpectations() throws IOException
{
    oldIn = System.in;
    oldOut = System.out;
    pipe = new PipedOutputStream();
    testIn = new PipedInputStream(pipe);
    mockOut = context.mock(PrintStream.class);
    System.setOut(mockOut);
    System.setIn(testIn);

    expectQuestion();
}

private void expectQuestion()
{
    Expectations exp = new Expectations()
    {
        {
            one(mockOut).println(main.QUESTION);
        }
    };
    context.checking(exp);

}

@After
public void reset()
{
    System.setIn(oldIn);
    System.setOut(oldOut);
}

@Test
public void fileChoiceReturnsFalse() throws IOException
{
    String FILE = "F\n";
    pipe.write(FILE.getBytes());

    assertFalse(main.promptStringOrFile());

    context.assertIsSatisfied(); // can avoid this call by using the right
                                    // test runner
}

and create two similar tests to check behaviour for input "I" and any other input (for which the question should be repeated once).

The promptStringOrFile() method is probably clearer if you use BufferedReader.readLine() rather than worrying about chars.

Community
  • 1
  • 1
DNA
  • 42,007
  • 12
  • 107
  • 146
  • well I rearranged it and it still didn't work, while using the mn variable. the mn variable is a mocked version of the class main that I am trying to test over. Here's the [code](http://ideone.com/rptC0) Here's the [test](http://ideone.com/VkvqM) – Adam Miller Apr 21 '12 at 21:31
  • Ah, the problem is that you're trying to mock a static method. JMock doesn't support this. See http://stackoverflow.com/questions/218813/jmock-mocking-a-static-method – DNA Apr 21 '12 at 21:53
  • Actually, I edited it and got a bit further... now I'm having trouble with the parameters on the arguments to a read function that accepts an array. I don't know how to do it. [Code](http://ideone.com/pPwCf),[tests](http://ideone.com/MwvzN) [Stack trace]( http://pastebin.com/WRMPT3Aj) – Adam Miller Apr 21 '12 at 22:31
  • Sorry about that. There doesn't seem to be a way in ideone to have a public piece of code that is also considered owned by the user... I thought you would be able to see them even if they were considered owned by me. I changed the visibility however. – Adam Miller Apr 22 '12 at 17:57