I'm learning Mockito. I am facing problem while creating mock for nested objects. See
public interface BaseManager {
public Query createQuery(String queryString);
}
and an implementation class for that
public class BaseManagerImpl implements BaseManager {
@Autowired
private SessionFactory sessionFactory;
// ...
}
Module level hibernate manager, for example:
public interface RegistrationManager {
@Transactional
public List<Country> getCountries();
}
and an implementation class for that
public class RegistrationManagerImpl implements RegistrationManager {
@Autowired
private BaseManager baseManager;
// ...
}
Now I'm facing problem in creating mocked base manager. My test class is:
public class MockitoTest {
private RegistrationManager registrationManager = new RegistrationManagerImpl();
@Mock private BaseManager baseManager;
@Mock private SessionFactory sessionFactory;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
// baseManager.setSessionFactory(sessionFactory);
registrationManager.setBaseManager(baseManager);
}
// ...
// @Test
}
Problem: sessionFactory is not instantiated inside baseManager. Please help creating mock object. Thanks in advance!
The problem is that you are creating a mock of BaseManager
but only BaseManagerImpl
has a SessionFactory
field. Mockito doesn't know about BaseManagerImpl
. In your code you create two mocks which are completely independent of each other.
Unit tests are about testing an unit. So you should test BaseManagerImpl
and RegistrationManagerImpl
separately.
So you test BaseManagerImpl
first:
public class BaseManagerImplTest {
private BaseManagerImpl target;
// ...
}
then you test RegistrationManagerImpl
:
public class RegistrationManagerImplTest {
private RegistrationManagerImpl target;
// ...
}
I suggest that you should use the name target
or something similar for your test target in your test class becaues it will make your code much more easier to read.
Another thing: If you test an object all of its dependencies should be mocked but you shouldn't care about the mocks' dependencies. You just mock their method invocations like:
Mockito.when(myMock.someMethod()).thenReturn(someResultObject);
You have to put the @InjectMocks
annotation before class you want to test and mock the methods which are called by the basemanger or sessionFactory.
public class MockitoTest {
@InjectMocks
private RegistrationManager registrationManager = new RegistrationManagerImpl();
@Mock private BaseManager baseManager;
@Mock private SessionFactory sessionFactory;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
// baseManager.setSessionFactory(sessionFactory);
registrationManager.setBaseManager(baseManager);
Mockito.when(baseManager.yourMethod()).thenReturn(someObject);
}
// ...
// @Test
}
Hope this is it you're looking for!
You cannot inject a mock
of SessionFactory
into a mock
of BaseManager
.
As you are testing RegistrationManagerImpl
, you just need to have a mock
of BaseManager
. You can use method stubbing so that the methods BaseManager
will return the stubbed values when those methods are called from RegistrationManagerImpl
methods. So, if you have a RegistrationManagerImpl
as this:
public class RegistrationManagerImpl implements RegistrationManager {
@Autowired
private BaseManager baseManager;
// ...
public String doSomething(){
return baseManager.process();
}
}
you can write your MockitoTest
as this:
public class MockitoTest {
@InjectMocks
private RegistrationManager registrationManager = new RegistrationManagerImpl();
@Mock private BaseManager baseManager;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
// ...
@Test
public void test() {
when(baseManager.process()).thenReturn("hello");
assertEquals("hello", registrationManager.doSomething());
}
}
And while testing BaseManager
, there you need to use mock
of SeesionFactory
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With