I am new with tests.
I have something like next code and wish to cover it with unitTests using the Mockito:
public void doSomeJob(){
//some code before
getMvpView().execute(getObservable());
//some code after
}
private Observable<Boolean> getObservable(){
return Observable.create(new ObservableOnSubscribe<Boolean>() {
#Override
public void subscribe(#NonNull ObservableEmitter<Boolean> e) throws Exception {
Thread.sleep(5000);
e.onNext(true);
e.onComplete();
}
});
}
so questions:
how correct write test for getMvpView().execute(getObservable()); using Mokito?
how can i verify result of getObservable()?
If your private method is not a part of the interface, i.e. cannot be reached from outside the class, it's not something you should test (presumably it's not, since it's private). Mockito in turn doesn't provide mocking of private methods. Thereby you either need to change your interface (make this data available outside) or leave it without testing.
What you should test is the effect of calling the public methods of your class under test. If you do so you will be able to freely refactor the implementation details later, and your tests will still verify that your class works as expected.
I suppose that your code is part of a presenter implementation and the getMvpView() method returns a view interface:
public class MvpPresenterImpl {
private MvpView view;
public void doSomeJob(){
//some code before
getMvpView().execute(getObservable());
//some code after
}
public void attachView(MvpView view) {
this.view = view;
}
private MvpView getMvpView() {
return view;
}
private Observable<Boolean> getObservable(){
return Observable.create(new ObservableOnSubscribe<Boolean>() {
#Override
public void subscribe(#NonNull ObservableEmitter<Boolean> e) throws Exception {
Thread.sleep(5000);
e.onNext(true);
e.onComplete();
}
});
}
}
You can test the effect of doSomeJob() like so:
public class MvpPresenterImplTest {
private MvpPresenterImpl presenter;
private MvpView mockView;
#Before
public void setUp() throws Exception {
// Create a mock view instance so that we can verify method calls on it
mockView = mock(MvpView.class);
// Create our object under test, and set it up with the mock view
presenter = new MvpPresenterImpl();
presenter.attachView(mockView);
}
#Test
public void doSomeJob_callsExecuteOnViewWithCorrectObserver() throws Exception {
// What we want to test is the effect of invoking a public method.
presenter.doSomeJob();
// Verify that the execute method has been called by your class
// under test, and save the parameter for later.
ArgumentCaptor<Observable<Boolean>> paramCaptor =
ArgumentCaptor.<Observable<Boolean>>forClass((Class)Observable.class);
verify(mockView).execute(paramCaptor.capture());
// Get the actual observable that the execute method was called with.
Observable<Boolean> param = paramCaptor.getValue();
// Get a test observer so that we can check what our Observable emits
// (TestObserver is a built-in feature of RxJava, not Mockito.)
TestObserver<Boolean> test = param.test();
// Assert that the Observable behaves as expected
test.assertComplete();
test.assertResult(true);
}
}
Related
I am getting the following exception when trying to mock the static method.
For SettingsUtility, static mocking is already registered in the
current thread To create a new mock, the existing static mock
registration must be deregistered
#Before
fun setUp() {
mockStatic(SettingsUtility::class.java) {
`when` { SettingsUtility.method(app) }.thenReturn { "" }}
}
The returned object's MockedStatic.close() method must be called upon completing the test or the mock will remain active on the current thread.
I am not sure if it is the same as how its done in Java. Hope this Java code snippet helps
private static MockedStatic<SettingsUtility> mockedSettings;
#BeforeAll
public static void init() {
mockedSettings = mockStatic(SettingsUtility.class);
}
#AfterAll
public static void close() {
mockedSettings.close();
}
Try doing this way, you will not get this error. It worked for me.
try(MockedStatic mocked = mockStatic(SettingsUtility.class)) {
mocked.when(SettingsUtility::method).thenReturn("whatever you want");
}
Building on #Sudha 's answer.
in Java you can use #BeforeClass and #AfterClass
private static MockedStatic<SettingsUtility> mockedSettings;
#BeforeClass
public static void init() {
mockedSettings = mockStatic(mockedSettings.class);
}
#AfterClass
public static void close() {
mockedSettings.close();
}
Mockito Inline works differently than the Mockito hence the failure. So what needs to be done is initialise and close the mocks explicitly.
You need to initialise the mockedStatic for your class
private MockedStatic<YourClassWithStaticMethod> mockedStatic;
Then add below code in BeforeEach and AfterEach
#BeforeEach
public void init() {
mockedStatic = mockStatic(YourClassWithStaticMethod.class);
}
#AfterEach
public void cleanup() {
mockedStatic.close();
}
And now you can set the mocked expectations.
mockedStatic.when(YourClassWithStaticMethod::staticMethodToMock).thenReturn(yourReturnedMockedObject);
I tried below and worked for me.
MockedStatic mockedStatic = mockStatic(SettingsUtility.class)
mocked.when(SettingsUtility::method).thenReturn("any thing");
...........
//do all stuf
and at last close the mock
mockedStatic.close();
SOLVED: Even if the getValue() on the Argument Captor shows you this, it is normal. To be honest I was expecting to see and instance on the OnLoginWithEmailCallback interface here. The problem on my side was related to a method call on mView which was generating a NPE. Works like a charm now.
ORIGINAL PROBLEM:
I am implementing my first unit test using Mockito in my MVP app and I need to mock the behaviour of a callback when the user is logging in. I am using Firebase to handle the authentication.
I followed a very good tutorial from here : https://fernandocejas.com/2014/04/08/unit-testing-asynchronous-methods-with-mockito/.
I am calling method on class under test. This method calls another one on the Auth Presenter which does the actual work
mPresenter.performLoginWithEmail(EMAIL, PASSWORD);
Then I am verifying that an underlining method in the Auth Presenter class was called. I try to capture the callback interface.
verify(mAuthPresenter, times(1)).login(mOnLoginWithEmailCallbackArgumentCaptor.capture(),
eq(EMAIL), eq(PASSWORD));
The problem is that getValue() from the Argument Captor returns an instance of the mPresenter (class under test) instead of the OnLoginWithEmailCallback interface class. Therefore I get an NPE.
mOnLoginWithEmailCallbackArgumentCaptor.getValue().onLoginWithEmailSuccess();
Here is the complete test class:
#RunWith(MockitoJUnitRunner.class)
public class LoginPresenterTest {
private static String EMAIL = "test#rmail.com";
private static String PASSWORD = "1234";
//class under test
private LoginPresenter mPresenter;
#Mock
AuthPresenter mAuthPresenter;
#Captor
private ArgumentCaptor<OnLoginWithEmailCallback> mOnLoginWithEmailCallbackArgumentCaptor;
#Mock
ILoginActivityView mView;
#Before
public void setupLoginPresenter() {
MockitoAnnotations.initMocks(this);
// Get a reference to the class under test
mPresenter = new LoginPresenter(mView, mAuthPresenter);
}
#Test
public void performLoginWithEmail() {
mPresenter.performLoginWithEmail(EMAIL, PASSWORD);
//wanting to have control over the callback object. therefore call capture to then call methods on the interface
verify(mAuthPresenter, times(1)).login(mOnLoginWithEmailCallbackArgumentCaptor.capture(),
eq(EMAIL), eq(PASSWORD));
mOnLoginWithEmailCallbackArgumentCaptor.getValue().onLoginWithEmailSuccess();
InOrder inOrder = Mockito.inOrder(mView);
inOrder.verify(mView).goToMap();
inOrder.verify(mView).hideProgressBar();
}
}
EDIT: This is the call to mAuthPresenter.login:
SOLVED: getLoginActivityView() was causing an NPE
public void performLoginWithEmail(String email, String password) {
mAuthPresenter.login(new OnLoginWithEmailCallback() {
#Override
public void onLoginWithEmailSuccess() {
getLoginActivityView().goToMap();
getLoginActivityView().hideProgressBar();
}
#Override
public void onLoginWithEmailFailed(String error) {
getLoginActivityView().hideProgressBar();
getLoginActivityView().showToast(error);
}
}, email, password);
}
I also tried using using doAnswer from Mockito:
doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
((OnLoginWithEmailCallback)invocation.getArguments()[0]).onLoginWithEmailSuccess();
return null;
}
}).when(mAuthPresenter).login(
any(OnLoginWithEmailCallback.class, EMAIL, PASSWORD));
Still, invocation.getArguments() return an instance of the class under test (LoginPresenter), so the same problem as before. Can you help me?
The problem was that i got confused by the Argument Captor which returned me an instance of the caller class (LoginPresenter). The problem in my case was with a method inside the anonymouse class OnLoginWithEmailCallback() which was throwing an NPE.
I need to mock some static methods, that's fine so far and can be done like this:
#RunWith(PowerMockRunner.class)
#PrepareForTest({DataService.class})
public class PlayersAllViewModelTest {
// mock objects
private PlayersAllContextHandler mContextHandler;
private PlayersAllAdapter mAdapter;
#Before
public void setUp() throws Exception {
mockStatic(DataService.class);
//define mocks
mContextHandler = mock(PlayersAllContextHandler.class);
mAdapter = mock(PlayersAllAdapter.class);
}
#Test
public void check_init_requests_are_done() throws Exception {
// create instance of viewmodel
new PlayersAllViewModel(mContextHandler, mAdapter);
// check dataservice is requested for method 'getAllPlayers()'
PowerMockito.verifyStatic();
DataService.getAllPlayers(any(DataServiceCallback.class));
}
I need to test the behavior for a given response (success() / failure()) answered in a callback. The normal way to do so is like this:
// define mock answer
doAnswer(new Answer<MyCallback<String>>() {
#Override
public MyCallback answer(InvocationOnMock invocation) throws Throwable {
MyCallback<Player> callback = (MyCallback<Player>) invocation.getArguments()[0];
callback.onFailure(new UnsupportedOperationException());
return null;
}
}).when(>>mocked class instance<<).myTestMethod(any(MyCallback.class));
Because is want to call a static method, i can't do it like that so. There's no mocked instance of a class that could fill the gap :(
Does anybody know what's the correct way to do it?
I am using Otto's event bus in my application. In one of my classes I am posting the event.
MyEvent myevent = new MyEvent();
uiBus.post(myEvent);
I am able to test the post method.
Now there is another class which is receiving the event.
//ReceiverClass.java
#Subscribe
public void onEventReceived(MyEvent myevent) {
callAMethod();
}
How do I unit test that this method was invoked. I tried with the following test code
#Mock
Bus uiBus;
#Test
public void testBusReceviedEvent() {
ReceiverClass instance = new ReceiverClass();
mockBus.register(instance);
MyEvent myevent = new MyEvent();
mockBus.post(myEvent);
//Test
verify(instance, times(1)).callAMethod();
}
But this code doesn't work.
I'm a little late to the party but here is an example of a class which works and accounts for async calls. Instead of Mocking EventBus we simply let it do it's thing and register it in the TestDriver class below.
The thing that makes this work is the CountDownLatch which, with the help of the abstract DataTransferCallback class, waits for latch.countDown() to be called or 5 seconds to go by.
Just register your test class and in the #Subscribe method, pass it back to the method that created the DataTransferCallback and do your assertions there.
#RunWith(AndroidJUnit4.class)
public class TestDriver {
private final CountDownLatch latch = new CountDownLatch(1);
private EventBus eventBus;
private DataTransferCallback transferCallback;
public abstract class DataTransferCallback {
abstract void onSuccess(DataTransfer event);
}
#Before
public void setUp() {
EventBus.getDefault().register(this);
eventBus = spy(EventBus.getDefault());
}
#SuppressWarnings("unchecked")
#Test
public void test200Resposne() throws InterruptedException {
// Get known good JSON
final String json = TestJSON.get200Response();
// Class under test
final Driver driver = new Driver(InstrumentationRegistry.getTargetContext());
final JsonParser jsonParser = new JsonParser();
//boolean to hold our test result
final boolean[] testPassed = new boolean[]{false};
transferCallback = new DataTransferCallback() {
#Override
public void onSuccess(DataTransfer event) {
assertNotNull(event);
verify(eventBus).post(event);
assertThat(event.getStatus(), is("OK"));
assertTrue(event.getData() != null);
testPassed[0] = true;
}
};
//Set our test EventBus object
driver.setEventBus(eventBus);
// The actual method under test
driver.parseData(jsonParser.parse(json));
// Set a countdown latch to wait for the result (5s)
latch.await(5000, TimeUnit.MILLISECONDS);
// will wait here until 5s or the #Subscrube method is hit
assertTrue(testPassed[0]);
}
//Because we want to examine EventBus Output, register it
//to this class and pass the event back through our custom abstract class
#Subscribe
public void onReceiveEventBusEvent(DataTransfer event) {
assertNotNull(transferCallback);
transferCallback.onSuccess(event);
//notify latch so that we can proceed
latch.countDown();
}
}
It does not work because instance is not a mock. You will have to verify the effects of callAMethod or put that method in another class and inject a mock of this new class into your ReceiverClass class.
For example...
private class ReceiverClass {
private MyNewClass theNewClassIWasTalkingAbout;
// Stick in a setter for that ^
#Subscribe
public void onEventReceived(MyEvent myevent) {
theNewClassIWasTalkingAbout.callAMethod();
}
}
Then your test will have to change slightly...
#Mock
private MyNewClass mockNewClass;
#InjectMocks // This will be the "solid" implementation of the thing you are trying to test, it is not a mock...
private ReceiverClass instance;
#Test
public void testBusReceivedEvent() {
mockBus.register(instance);
MyEvent myevent = new MyEvent();
mockBus.post(myevent);
verify(mockNewClass, times(1)).callAMethod();
}
Hope this helps.
What I want to do is to create a simple in-memory cache just to try Observables out. However I got stuck because I don't understand how to create an observable. This is the code I have gotten so far:
public class MovieCache {
MovieWrapper movieWrapper;
public Observable<MovieWrapper> getMovies() {
//How to create and return an Observable<MovieWrapper> here?
}
public void setCache(MovieWrapper wrapper) {
movieWrapper = wrapper;
}
public void clearCache() {
movieWrapper = null;
}
}
In the getMovies() method I want to create an Observable and return my local field movieWrapper to the subscriber. How can I do this? I tried with using new Observable.just(movieWrapper) but it results in a null exception.
Take a look at this tutorial as it does exactly what you are looking for. Basically you use defer() to make sure you always get the latest version of your cached object:
public class MovieCache {
MovieWrapper movieWrapper;
public Observable<MovieWrapper> getMovies() {
return Observable.defer(new Func0<Observable<MovieWrapper>>() {
#Override
public Observable<MovieWrapper> call() {
return Observable.just(movieWrapper);
}
});
}
public void setCache(MovieWrapper wrapper) {
movieWrapper = wrapper;
}
public void clearCache() {
movieWrapper = null;
}
}
defer() makes sure that you will get the object upon subscription to the Observable not on creation.
Note however that, according to the author of the post:
The only downside to defer() is that it creates a new Observable each
time you get a subscriber. create() can use the same function for each
subscriber, so it's more efficient. As always, measure performance and
optimize if necessary.
As already said, accepted answer has downside
it creates a new Observable each time you get a subscriber
But it is not the only one.
Consumer won't receive any value if he calls getMovies().subscribe(...) before setCache(...) is called.
Consumer should resubscribe if he want to receive any updates (let's say setCache() can be called multiple times.
Of course all of them can be irrelevant in your scenario. I just want to show you another way (I'm sure there are many more).
You can use BehaviorSubject in order to eliminate all these disadvantages.
public class MovieCache {
private BehaviorSubject<MovieWrapper> mMovieCache = BehaviorSubject.create();
public void setCache(MovieWrapper wrapper) {
mMovieCache.onNext(wrapper);
}
public Observable<MovieWrapper> getMovieObservable() {
//use this if consumer want to receive all updates
return mMovieCache.asObservable();
}
public MovieWrapper getMovie() {
//use this if consumer want to get only current value
//and not interested in updates
return mMovieCache.getValue();
}
public void clearCache() {
//CAUTION consumer should be ready to receive null value
mMovieCache.onNext(null);
//another way is to call mMovieCache.onCompleted();
//in this case consumer should be ready to resubcribe
}
public static class MovieWrapper {}
}
Take a look at BehaviorSubject marble diagram.