Take this code as an example:
public void handleMoveForwardRequest(String[] command)
{
// userId should be the first element
User user = getUser(command[0]);
movement.moveUserForward(user);
// this depends on the socket server API for the exact call
extension.sendTheResponse(command, user, user.getCurrentLocation());
}
This code is a little unrealistic, but humour me for this example. Assume that we can pass in a mocked Movement with a setter. We are going to use Mockito's 'answer' call to update the location for the User (which cannot be mocked). They suggest not to use it, but we aren't testing the Movement class.
//Assume that the mock objects were previously instantiated
@Test
public void canMoveForward()
{
String[] command = new String[] {"123", "Forward"};
handler.setMovement(mockMovement);
// use hamcrest matchers for the object we're expecting
when(mockMovement.moveUserForward((User) anyObject()))
.thenAnswer(new Answer() { Object answer(InvocationOnMock invocation)
{
Object[] args = invocation.getArguments();
User user = (User) args[0];
user.setLocation(user.getCurrentLocationX() + 1, user.getCurrentLocationY());
return "called with arguments: " + args;
}
});
User user = getUser(command[0]);
handler.handleMoveRequest(command);
verify(mockExtension).sendTheResponse(command, mockUser, user.getCurrentLocation());
}
When 'moveUserForward' is called a new 'Answer' is created. It updates the location of the user to some arbitrary value. In this case we added 1 unit to the X location. Our test will pass because the User is a static reference to that object. The location actually is updated for the object that the SUT gets, and the object our test checks for.
This can seem complicated at first, and it probably isn't necessary because most TDD code is cleaner than this. However, in complicated systems with legacy code you may stumble across a similar situation.
No comments:
Post a Comment