In my application I use observer pattern for some operations and I want to test them in unit tests. The problem is that I don't know how can I test observers using junit/mockito/something else. Any help?
For example this is my unit test:
@Before
public void setUp() throws IOException, Exception {
observer = new GameInstanceObserver(); // observable (GameInstance) will call update() method after every change
GameInstance.getInstance().addObserver(observer); // this is observable which is updated by serverService
}
@Test(expected = UserDataDoesntExistException.class)
public void getRoomUserData_usingNullKey_shouldThrowUserDataDoesntExist() throws InterruptedException, UserDataDoesntExistException {
serverService.createRoom("exampleRoom"); // this operation is asynchronous and updates GameInstance data (as I wrote before GameInstance is Observable)
Thread.sleep(400); // how to do it in better way?
GameInstance gi = (GameInstance) observer.getObservable();
assertTrue(gi.getRoom("exampleRoom").getRoomId().equals("exampleRoom"));
}
I would like to not use Thread.sleep()
and use it in that way (or similar):
@Test(expected = UserDataDoesntExistException.class)
public void getRoomUserData_usingNullKey_shouldThrowUserDataDoesntExist() throws InterruptedException, UserDataDoesntExistException {
serverService.createRoom("exampleRoom"); // this operation is asynchronous and updates GameInstance data (as I wrote before GameInstance is Observable)
waitUntilDataChange(GameInstance.getInstance()); // wait until observable will be changed so I know that it notified all observer and I can validate data
GameInstance gi = (GameInstance) observer.getObservable();
assertTrue(gi.getRoom("exampleRoom").getRoomId().equals("exampleRoom"));
}
Mockito provides a special Timeout option to test if a method is called within stipulated time frame.
With Mockito, you create a mock, tell Mockito what to do when specific methods are called on it, and then use the mock instance in your test instead of the real thing. After the test, you can query the mock to see what specific methods were called or check the side effects in the form of changed state.
The thenReturn() methods lets you define the return value when a particular method of the mocked object is been called. The below snippet shows how we use thenReturn to check for multiple values. Iterator i = mock(Iterator.
Mockito can mock asynchronous classes.
If I understand correctly, the problem is not really to test the observer, but to test the result of an asynchronous method call. To do that, create an observer which blocks until its update() method has been called. Something like the following:
public class BlockingGameObserver extends GameInstanceObserver {
private CountDownLatch latch = new CountDownLatch(1);
@Override
public void update() {
latch.countDown();
}
public void waitUntilUpdateIsCalled() throws InterruptedException {
latch.await();
}
}
And in your test:
private BlockingGameObserver observer;
@Before
public void setUp() throws IOException, Exception {
observer = new BlockingGameObserver();
GameInstance.getInstance().addObserver(observer);
}
@Test
public void getRoomUserData_usingNullKey_shouldThrowUserDataDoesntExist() throws InterruptedException, UserDataDoesntExistException {
serverService.createRoom("exampleRoom");
observer.waitUntilUpdateIsCalled();
assertEquals("exampleRoom",
GameInstance.getInstance().getRoom("exampleRoom").getRoomId());
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With