user1611830
user1611830

Reputation: 4857

how to mock with mockito

I have a method in my MainActivity (Android) and I want to mock the A instance :

public void some_method() {
    A a = new A(); 
    ....   
}

so I created a kind of factory class as such

public class SomeFactory(){

 // some constructor
public A populateWithParameter(Parameter parameter){
 return new A(parameter)
} 
}

and the method above turns into

public void some_method(SomeFactory someFactory) {
        A a = someFactory.populateWithParameter(parameter); 
        a.method_call()        
        ....   
    }

I tried this

@Mock
    SomeFactory someFactory;

public void testSomeMethod() throws Exception {
        SomeFactory someFactory = new SomeFactory();
        when(someFactory.populateWithParameter(
                some_parameter)).thenReturn(null);

        mainActivity.some_method(someFactory);
...
    }

but I get this error message

    org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);

Upvotes: 0

Views: 280

Answers (3)

epsilones
epsilones

Reputation: 11609

From the point of view of response of @DiscoS2, there is indeed an issue with this declaration

MockitoAnnotations.initMocks(this);

You should use instead SomeFactory someFactory = mock(SomeFactory.class) and then follow the updated response of @DiscoS2

Upvotes: 0

StuStirling
StuStirling

Reputation: 16181

You are not mocking your factory. Also, wrong method call.

Do this instead.

    SomeFactory someFactory = mock(SomeFactory.class)
    when(someFactory.populateWithParameter(
            some_parameter)).thenReturn(null);

    mainActivity.some_method(someFactory);

UPDATE

Your code has changed so for completeness this is what your test should look like. In the updated code above, you were overwriting your mock with a real object. Assuming your objects are correctly set up. Notice the different syntax for providing a return object. I think this is more readable.

@Mock SomeFactory mockFactory;

@Before
public void setUp() {
    MockitoAnnotations.initMocks(this); // set up annotated mocks
}

@Test
public void testSomeMethod() {
    A subject = new A();
    doReturn(subject).when(mockFactory)
                        .populateWithParameter(any(Parameter.class));
    main_activity.some_method(mockFactory);
    verify(mockFactory,times(1)).populateWithParameter(any(Parameter.class));
}

Best Practices

  • When naming methods and variables, use camelCase. So main_activity becomes MainActivity, some_method becomes SomeMethod.

Upvotes: 1

Emmanuel
Emmanuel

Reputation: 13223

You need a way to overwrite the instance of A from your test. Typically this is done using an injection framework. For a simple case, you can make the field under test protected (assuming the test class is in the same package as the class under test).

The error you are seeing comes interacting with a "real" object as if it was a mock.

In this case SomeFactory is a real object so it cannot be when()ed

Upvotes: 0

Related Questions