Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock a private dao variable?

I have a dao.create() call that I want to mock when testing a method. But I am missing something as I'm still getting NPE. What is wrong here?

class MyService {
    @Inject
    private Dao dao;

    public void myMethod() {
        //..
        dao.create(object);
        //
    }
}

How can I mock out the dao.create() call?

@RunWith(PowerMockRunner.class)
@PrepareForTest(DAO.class)
public void MyServiceTest {

    @Test
    public void testMyMethod() {
        PowerMockito.mock(DAO.class);

        MyService service = new MyService();
        service.myMethod(); //NPE for dao.create()
    }
}
like image 736
membersound Avatar asked Nov 30 '12 12:11

membersound


People also ask

Can we mock a private class?

Hi, I would strongly advice against mocking private inner classes since usually there are other more elegant ways of testing your problem and the test case can end up being very complex. Personally I would try to refactor the code if the test gets too complex or write an integration test instead of mocking at all.

How do you call a private method in Mockito?

For Mockito, there is no direct support to mock private and static methods. In order to test private methods, you will need to refactor the code to change the access to protected (or package) and you will have to avoid static/final methods.

Can you mock constructor?

Mocking constructorsWith the mockConstruction you can mock calls made to the constructor. For example, we mock the constructor for the class Dog . The test code is inside a try with resources to limit the scope. When your code calls the constructor inside the try statement, it returns a mock object.


1 Answers

You are not injecting the DAO. With mockito you can change your test class to use @InjectMocks and use mockito runner.

@RunWith(MockitoJUnitRunner.class)
public void MyServiceTest {
    @Mock
    private Dao dao;
    @InjectMocks
    private MyService myService;
    ...
}

You can read more about InjectMocks at Inject Mocks API

Simpler way is changing your injection to injection by constructor. For example, you would change MyService to

class MyService {
    ...
    private final Dao dao;

    @Inject
    public MyService(Dao dao) {
        this.dao = dao;
    } 
    ...
}

then your test you could simple pass the mocked DAO in setup.

...
@Mock
private Dao dao;

@Before
public void setUp() {
    this.dao = mock(Dao.class);
    this.service = new MyService(dao);
}
...

now you can use verify to check if create was called, like:

...
   verify(dao).create(argThat(isExpectedObjectBeingCreated(object)));
}

private Matcher<?> isExpectedObjectBeingCreated(Object object) { ... }

Using injection by constructor will let your dependencies clearer to other developers and it will help when creating tests :)

like image 161
Caesar Ralf Avatar answered Oct 11 '22 02:10

Caesar Ralf