how to test picasso using unit-test and mockito - android

I am learning how to unit-testing in android studio. as shown below, I would like to test the two methods shown below in the code section.
can you please help and guide me how to test this method?
code
public RequestCreator requestCreatorFromUrl(String mPicUrl)
{
return Picasso.with(mCtx).load(mPicUrl);
}
public void setImageOnImageView(RequestCreator requestCreator, ImageView mImagView)
{
requestCreator.into(mImagView);
}
My Attempts:
#Test
public void whenRequestCreatorFromUrlTest() throws Exception {
Picasso mockPicasso = mock(Picasso.class);
File mockFile = mock(File.class);
Assert.assertNotNull("returned Request creator is not null",
mockPicasso.load(mockFile));
}

First method you can't test, you'd have to verify the call of a static method which is not supported in Mockito.
You could split the method in
public RequestCreator requestCreator() {
return Picasso.with(mCtx);
}
and
public void load(RequestCreator requestCreator, String picUrl) {
requestCreator.load(picUrl)
}
and test the load(...) method.
Second method:
Mock the requestCreator. Mock the imageView.
Call the method with your mocked objects.
Then verify requestCreator.into(...) was called with the supplied parameter:
Mockito.verify(requestCreator).into(imageView);

Related

Why is Mockito boolean stub being ignored

I have a method that checks a condition and does some work.
public void doSomeWork(){
if(!UtilityClass.someCondition()){
context.getmeSomething();
}
}
My test looks like this.
#Test
public void test(){
myClass.doSomeWork();
PowerMockito.verifyStatic(UtilityClass.class)
when(UtilityClass.someCondition()).thenReturn(false);
verify(mContext, times(1)).getmeSomething();
}
The problem is the stub is simply ignored. The test passes regardless of the stub result. By the same token, never verification on fails and I get Never wanted at the test but wanted at my class under test from Mockito. My question is why the boolean stub being ignored?
Update
I am not sure if it is significant with my original question, but the Utility class is included in the prepare for test and has mockStatic call in setUp.
Ordering of your statements!
Register your mocks and behaviour of it.
Call the method
Verify
EDIT:
you should also make sure, that UtilityClass is a mock. You can't stub actual classes, just mocks of them.
#Rule
public MockitoRule rule = MockitoJUnit.rule();
#Mock
private UtilityClass utilityClassMock;
private MyClass myClass;
#Before
public void beforeEachTest() {
myClass = new MyClass(utilityClassMock);
}
#Test
public void test(){
when(utilityClassMock.someCondition).thenReturn(false);
myClass.doSomeWork();
verify(mContext, times(1)).getmeSomething();
}
Just like GabrielJoerg said the stubbing should happen first before the method call. But the real issue here is that when stubbing, you should avoid calling verifyStatic. Here is what worked for me.
#Test
public void test(){
when(UtilityClass.someCondition()).thenReturn(false);
myClass.doSomeWork();
verify(mContext, times(1)).getmeSomething();
}

ArgumentCaptor captures wrong class

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.

how to test private Observable inside public method?

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);
}
}

How to test a static method using mock() and spy()

the below posted method in the code section contains a static method which is "with()". I want to test the code in below, so I coded the test of this method
as shown in the testing section.
i tried to test the method using both of "spy()" and "mock()" but the test fails alwyas.
please let me know how can I test a method returns void?
code
public RequestCreator requestCreatorFromUrl(String picUrl) {
return Picasso.with(mCtx).load(picUrl);
}
testing:
public class ValidationTest {
#Mock
private Context mCtx = null;
#Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
#Before
public void setUp() throws Exception {
mCtx = Mockito.mock(Context.class);
Assert.assertNotNull("Context is not null", mCtx);
}
#Test
public void whenRequestCreatorFromUrlTest() throws Exception {
Picasso picasso = Picasso.with(mCtx);
Picasso spyPicasso = spy(picasso);
Uri mockUri = mock(Uri.class);
RequestCreator requestCreator = Picasso.with(mCtx).load(mockUri);
RequestCreator spyRequestCreator = spy(requestCreator);
doReturn(spyRequestCreator).when(spyPicasso.load(mockUri));
//when(spyPicasso.load(mockUri)).thenReturn(spyRequestCreator);
RequestCreator actual = spyPicasso.load(mockUri);
Assert.assertEquals(requestCreator, actual);
}
Usually, if you end up using PowerMock, that’s a good sign that you most possibly are on the wrong way.
What if instead of directly referring to Picasso, you create a component, whose responsibility will be to load an image, let's say class ImageLoader. What will this give to you?
Separation of concerns: if tomorrow you decide to move to Glide, you shouldn't change each and every class where you were using Picasso, you will just change implementation of ImageLoader. Other components are non-wiser of these changes, because they are dependent on an abstraction, not on implementation
Seam: this will allow you easily mock dependencies in order to perform unit testing
This will be our abstraction:
interface ImageLoader {
RequestCreator load(String url);
}
Let’s provide an implementation:
class ImageLoaderImpl implements ImageLoader {
private final Picasso picasso;
public ImageLoaderImpl(Context context) {
this.picasso = Picasso.with(context);
}
#Override
public RequestCreator load(String url) {
return picasso.load(url);
}
}
Now, in your components whenever you need Picasso use ImageLoader instead.
Thus, your method becomes following:
public static RequestCreator requestCreatorFromUrl(String picUrl) {
return imageLoader.load(picUrl);
}
Then your test will look like this:
#Test
public void test() {
ImageLoaderImpl imageLoader = Mockito.mock(ImageLoaderImpl.class);
RequestCreator expected = Mockito.mock(RequestCreator.class);
String TEST_URL = "https://www.some.url/img.jpg";
when(imageLoader.load(TEST_URL)).thenReturn(expexted);
RequestCreator actual = clazzToTest.requestCreatorFromUrl(TEST_URL);
assertEquals(expected, actual);
}
No mocking of static method, no PowerMock needed.
From the Mockito's FAQ:
What are the limitations of Mockito
...
Cannot mock static methods
Use PowerMock instead. Here you will find the detailed instruction about how to mock the static methods.
Update
In order to apply the PowerMock to your test you need to:
Add #PrepareForTest at test class level:
#PrepareForTest(Picasso.class)
public class ValidationTest {
...
}
Call PowerMockito.mockStatic() to mock a static class
PowerMockito.mockStatic(Picasso.class);
Just use Mockito.when() to setup your expectation:
Mockito.when(Picasso.with(mCtx)).thenReturn(requestCreator);
The same set of steps is applicable for the RequestCreator.class.
P.S. I can make mistakes because I do not know the API of 3rd party library you use.

Verify a static method was called by another static method in PowerMock

I have a Tool class with two static methods, doSomething(Object) and callDoSomething(). The names are intuitive in that callDoSomething delegates its call to doSomething(Object);
public class Tool
{
public static void doSomething( Object o )
{
}
public static void callDoSomething()
{
doSomething( new Object());
}
}
I have a Test class for Tool and I'd like to verify if doSomething(Object) was called (I want to do Argument Matching too in the future)
#RunWith( PowerMockRunner.class )
#PrepareForTest( { Tool.class } )
public class ToolTest
{
#Test
public void toolTest()
{
PowerMockito.mockStatic( Tool.class );
Tool.callDoSomething();// error!!
//Tool.doSomething();// this works! it gets verified!
PowerMockito.verifyStatic();
Tool.doSomething( Mockito.argThat( new MyArgMatcher() ) );
}
class MyArgMatcher extends ArgumentMatcher<Object>
{
#Override
public boolean matches( Object argument )
{
return true;
}
}
}
Verify picks up doSomething(Object) if it's called directly. I've commented this code out above. Verify does NOT pick up doSomething(Object) when using callDoSomething, (this is the code shown above). This is my error log when running the code above:
Wanted but not invoked tool.doSomething(null);
However, there were other interactions with this mock.
at org.powermock.api.mockito.internal.invocation.MockitoMethodInvocationControl.performIntercept(MockitoMethodInvocationControl.java:260)
at org.powermock.api.mockito.internal.invocation.MockitoMethodInvocationControl.invoke(MockitoMethodInvocationControl.java:192)
at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:105)
at org.powermock.core.MockGateway.methodCall(MockGateway.java:60)
at Tool.doSomething(Tool.java)
at ToolTest.toolTest(ToolTest.java:22)
... [truncated]
I'd like to avoid making any changes to the Tool class. My question is, how can I verify doSomething(Object) was called from callDoSomething(), as well as perform some argument matching on doSomething's param
It sounds like you want to use a static spy (partial mock). The section of the PowerMock documentation that talks about mocking static has a note in the second bullet that could be easily missed:
(use PowerMockito.spy(class) to mock a specific method)
Note, in your example you're not actually mocking the behavior, just verifying the method is called. There's a subtle but important difference. If you don't want doSomething(Object) to be called you'd need to do something like this:
#Test
public void toolTest() {
PowerMockito.spy(Tool.class); //This will call real methods by default.
//This will suppress the method call.
PowerMockito.doNothing().when(Tool.class);
Tool.doSomething(Mockito.argThat( new MyArgMatcher() ));
Tool.callDoSomething();
//The rest isn't needed since you're already mocking the behavior
//but you can still leave it in if you'd like.
PowerMockito.verifyStatic();
Tool.doSomething(Mockito.argThat( new MyArgMatcher() ));
}
If you still want the method to fire though, just remove the two lines for doNothing(). (I added a simple System.out.println("do something " + o); to my version of Tool.java as an additional verification of doNothing().)
You can do your validation with this:
public class Tool{
public static boolean isFromCallDoSomethingMethod= false;
public static void doSomething(Object o){
}
public static void callDoSomething() {
doSomething(new Object());
isFromCallDoSomethingMethod= true;
}
}
You can do the verification as:
if(Tool.isFromCallDoSomethingMethod){
//you called doSomething() from callDoSomething();
}
REMEMBER
Don't forget to do the validation if you call the doSomething() from another way that is not from callDoSomething(), you can do this by ussing Tool.isFromCallDoSomethingMethod = false
Is this what you want?

Categories

Resources