TL;DR: Use a doAnswer()
with a new Answer<Observable<Type>>()
if you have to mock observables.
Today I wrote my first test where I had to mock an observable interface:
public interface UserDatabase {
Observable<User> readUser(String username);
}
where the User
model is:
public class User {
private String name;
private String password;
public User(String name, String password) {
this.name = name;
this.password = password;
}
public String getName() {
return name;
}
public String getPassword() {
return password;
}
}
Solution
In my test class (named UserDatabaseTest
), I first mocked the interface:
@Mock
UserDatabase mockUserDatabase;
Then, my setup()
method is:
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
// Mock one user answer
doAnswer(new Answer<observable<user>>() {
@Override
public Observable<user> answer(InvocationOnMock invocation) throws Throwable {
return Observable.just(user);
}
}).when(mockUserDatabase).readUser(USER_NAME);
}
where USER_NAME
is a String
.
To use it, you need to attach an observer and assert:
@Test
public void canGetUser() {
Observable<User> userObservable = mockUserDatabase.readUser(UserCommon.USER_NAME);
TestObserver<User> userTestObserver = new TestObserver<>();
userObservable.subscribe(userTestObserver);
userTestObserver.assertReceivedOnNext(Collections.singletonList(user));
}
This is quite simple.
Alternative
Note: This I haven't tried yet, but here it goes...
If you want to return a particular method call, you can use:
when(mockUserDatabase.readUser(USER_NAME))
.thenReturn(Observable.just(new User(...)));
This is shorter (if it works) :)
HTH,
Member discussion: