Showing posts with label Test Driven Development. Show all posts
Showing posts with label Test Driven Development. Show all posts

Sunday, 6 April 2014

Mockito Spies

That is the collective noun, not the verb, although I suppose Mockito is spying...

Spies are used to make existing classes into Mockito classes. Say your class under test hooks into a Java listener, so you want some kind of dummy listener for it to hook into. You can't do this with Mockito (at least I can't find a way), but you can make your own:

//listener interface
public interface SomethingListener {
    //change that sends the event
    public void somethingChanged(EventObject e);
}

//our little dummy listener provider
public class DummyListenerProvider {

    private SwitchListener listener;

    //this is used by the class under test
    public void addSwitchListener(SwitchListener listener) {
        this.listener = listener;
    }

    //send event, saying the class is the source
    public void triggerEvent() {
        this.listener.somethingChanged(new EventObject(this));
    }

    //used by the event consumer when the event occurs
    public void switchMeOn(boolean isTrue) {
    }
}

Cool, but you still want all the nice little trinkets that come with the Mockito objects. This is where spies come in. You just wrapper the class using spy instead of mock:

DummyListenerProvider spyListenerProvider = spy(new DummyListenerProvider());

ClassUnderTest underTest = new ClassUnderTest(spyListenerProvider);

spyListenerProvider.triggerEvent();

verify(spyListenerProvider).switchMeOn(true);

Saturday, 5 April 2014

Mockito - An Elegant Stub for a More Civilised Age

In software development, we make use of something called "stubs". These are bits of code that don't do anything at the moment, but allow us to continue coding elsewhere as if they do, replacing them later. They are also used in testing to substitute for more complex objects, and this is where "mocking" (creating "mock" objects) has been developed in object-oriented programming and test-driven development.

As an extension to the college work I've been doing, I've been looking into using mock libraries for unit testing and I've come across Mockito:

The mock objects it creates are, well, amazing to say the least. Say we've got an interface that, in turn, allows us to create a read I/O stream and a write I/O stream, for networking. The interface would look something like this:

//simple interface wrapper around a network socket
public interface MySocket {
    //creates a read I/O stream
    public BufferedReader getBufferedReader() throws IOException;
    //creates a write I/O stream
    public PrintWriter getPrintWriter() throws IOException;
    //indicates that a connection has been successfully made
    public boolean isConnected();
    //closes the connection
    public void close() throws IOException;
}

Now I can actually mock this interface with Mockito in the unit test:
import static org.mockito.Mockito.*;
...
MySocket socket = mock(MySocket.class);
You can now use this mock socket interface in whatever need the interface, so:
SocketThread socketThread = new SocketThread(socket);

Now, unfortunately, the mock doesn't really do anything other than just record what happens to it. Say SocketThread calls socket.close internally when it runs:
//this is in SocketThread.run
socket.close();
...
//if this isn't true, you'll get an exception
verify(socket).close();
Useful, but it becomes a bit more powerful when we add mocks for the input and output streams:
PrintWriter printWriter = mock(PrintWriter.class);
BufferedReader bufferedReader = mock(BufferedReader.class);
when(socket.getBufferedReader()).thenReturn(bufferedReader);
when(socket.getPrintWriter()).thenReturn(printWriter);
You can control exactly what the mock does and when it does it. Very useful for unit testing (and I haven't even begun to use all it's capabilities).