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.
Related
I have a class, which has a lot of dependencies.
#Service
public class TestClass {
#Inject
private DependencyA dependencyA;
#Inject
private DependencyB dependencyB;
#Inject
private DependencyC dependencyC;
// .
// .
// .
// .
#Inject
private DependencyZ dependencyZ;
public boolean testMethod() {
try {
dependencyA.methodA();
dependencyB.methodB();
dependencyC.methodC();
dependencyD.methodD();
return true;
} catch (StaleObjectStateException e) {
return false;
}
}
}
Now I want to mock one of the dependencies and throw exception to test the catch block of this class.
So following is my test, where I mock dependencyB and throw StaleObjectStateException when dependencyB.methodB(); called.
public class TestClassIT {
#InjectMocks
private TestClass testClass;
#InjectMocks
private CustomRuleEngine customRuleEngine;
#Mock
private DependencyB dependencyB;
#Before
public void init() {
MockitoAnnotations.initMocks(TestClass.class);
}
#Test
public void testOnSuccessRuleAfterCreate() throws Exception {
setupRequestContextWithFullPermission();
when(dependencyB.methodB(any())).thenThrow(new StaleObjectStateException("f", "f"));
// and expect exception.
}
}
However, it doesn't work because all other dependencies of TestClass are injected as a null. How to solve this?
As I mentioned this class has a lot of dependencies and I can't mock each. The requirement is just of mock dependencyB.methodB();
This is one of the cases where property injection is hurting.
Change TestClass to use constructor injection. Then you can instantiate it in your test yourself and inject whatever you want.
You have to define all your dependencies as mocks, not just DependencyB, so Mockito can do the injection. Even if you do not mock their methods, this way, there won't be null fields in your TestClass.
#Mock
private DependencyA dependencyA;
#Mock
private DependencyB dependencyB;
#Mock
private DependencyC dependencyC;
This question already has answers here:
Injecting #Autowired private field during testing
(6 answers)
Closed 3 years ago.
I have two classes, Parent and Child, and want to unit test some methods in the Child class using Mockito.
public abstract class Parent {
#Resource Service service;
}
#Service // spring service
public class Child extends Parent {
private AnotherService anotherService;
#Autowired
Child(AnotherService anotherService) {
this.anotherService = anotherService;
}
public boolean someMethod() {
}
}
My test class looks like below:
#RunWith(MockitoJUnitRunner.class)
public class ChildTest {
#Mock
Service service;
#Mock
AnotherService anotherService;
#InejctMocks
Child classToTest;
#Test
public void testSomething() {
assertTrue(classToTest.someMethod());
}
}
And the issue I am facing is that anotherService is being mocked properly but service is null. Can someone please tell me how to successfully mock both of the services (dependencies) in my test class?
inside the test, class add this and try
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
If you use Spring:
#SpringBooTest
#RunWith(SpringRunner.class)
#MockBean(Resource.class)
class TestClass{
#Autowire
private Resource resource;
#Autowire
private Service service;
#Test
public void test(){
Mockito.when(resource).getSomething(Mockito.any(),Mockito.any()).thenThrow(new RuntimeException(""));
service.doSomething();
}
}
You can use Mockito:
// Or use MockitoAnnotations.initMocks(testClass); in before method instead rule
#RunWith(MockitoJUnitRunner.class)
class TestClass{
#Mock
Resource resource;
#InjectMocks
Service service;
#Test
public void test(){
Mockito.when(resource).getSomething(Mockito.any(),Mockito.any()).thenThrow(new RuntimeException(""));
service.doSomething();
}
}
I have this Junit test, where I have an object that I want to mock the BackendHotelService object; I used #MockBean and #Autowired, but in both I got a java.lang.NullPointerException when running the test
#Component
public class FindHotelDataRequestTransformer extends HotelDataRequestTransformer {
public FindHotelDataRequestTransformer(BackendHotelService backendHotelService) {
super (backendHotelService);
}
..
}
and the test:
public class FindHotelDataRequestTransformerTest {
#MockBean
//#Autowired
private BackendHotelService backendHotelService;
private FindHotelDataRequestTransformer transformer;
#Before
public void setUp() {
transformer = new FindHotelDataRequestTransformer( backendHotelService);
}
the backendHotelService is never used
When creating a new FindHotelDataRequestTransformer, do you access any fields of backendHotelService?
if so you will need to mock the response.
Try below
Mockito.when(backendHotelService.name()).thenReturn("test);
In my class, dependencies are injected by Spring. During testing, I am using mocks. I am getting null pointer exception when I call sys.getId("abc12345") in the following code. I am wondering how to write a unit test that gets 100% coverage.
Class under test:
public class SystemUT implements SUTIface{
#Inject
private AccountLookupDAO dao;
#Inject
private OrchService service;
public Response perform(Request req){
String sellerId = getId(request.getSeller().getNum());
String buyerId = null;
if(req.getBuyerId){
buyerId = getId(request.getBuyer().getNum())
}
service.execute(Request,sellerId,buyerId)
}
String getId(String num){
PrefAcct prefAcctObj = dao.lookupPrefId(num,Consants.StrArr);
PrefSysOfRecObj sorObj= prefAcctObj.getSysOfRecord();
return sorObj.getId();
}
}
Unit test:
public Class SystemUTTest{
#Mock
SystemUT sys;
#Mock
AccountLookupDAO daoMock;
#Mock
OrchService serviceMock;
#Mock
PrefAcct prefAcctObj;
#Mock
PrefSysOfRecObj sorObj;
#Before
public void setup(){
Whitebox.setInternalState(sys, daoMock, serviceMock);
}
#Test
public test getId(){
when(dao.lookupPrefId(any(String.class), any(String[].class))).thenReturn(prefAcctObj);
when(prefAcctObj.getSysOfRecord()).thenReturn(sorObj);
when(sorObj.getId()).thenReturn("185");
assertEquals("185",sys.getId("abc12345"));
}
}
Your problem is that your SystemUT class doesn't have its dependencies injected. You could have Spring do this by using their JUnitRunner, but it's not really a unit test then, since you'd be letting Spring dictate which dependencies get injected. Really, you want to control them, and one way to do that is to transform your class to expose its dependencies via a constructor:
public class SystemUT implements SUTIface{
private final AccountLookupDAO dao;
private final OrchService service;
#Inject
public SystemUT(AccountLookupDAO dao, OrchService service) {
this.dao = dao;
this.service = service;
}
}
This will function identically to your current approach since Spring is able to inject dependencies using a constructor annotated with #Inject. Now, when you instantiate your SystemUT class for test, pass mocked objects for its dependencies:
#Mock
AccountLookupDAO daoMock;
#Mock
OrchService serviceMock;
private SystemUT sys;
#Before
public void setup(){
sys = new SystemUT(daoMock, serviceMock);
Whitebox.setInternalState(sys, daoMock, serviceMock);
}
I am using Junit4 and Mockito for test cases, in the following code dbprop.getProperty("config") is throwing a NullPointerException because dbProp is null. Please help me out why it was not mocked?
public abstract class BaseClass {
#Autowired
protected DBproperties dbprop;
}
public class SampleClass extends BaseClass {
#Autowired
private OrderService orderService;
valdiateOrder(String input) {
String config = dbprop.getProperty("config");
}
}
public class TestSampleClass {
#InjectMocks
SampleClass sampleClass;
#Mock
private OrderService orderService;
#Test
public void testValidateOrder() {
DBproperties dbprop = mock(DBproperties .class);
when(dbprop.getProperty("config")).thenReturn("xxxx");
assertNotNull(SampleClass.valdiateOrder("xxx"));
}
}
Your dbprop mock has not been injected into sampleClass, you need to add:
#Mock
private DBproperties dbprop;
Then remove the dbprop mock creation from your test method:
#Test
public void testValidateOrder() {
// DBproperties dbprop = mock(DBproperties .class); <-- removed
when(dbprop.getProperty("config")).thenReturn("xxxx");
assertNotNull(SampleClass.valdiateOrder("xxx"));
}
Next, to ensure mocks are injected when using the #InjectMocks annotations you need to either add the following runner:
#RunWith(MockitoJUnitRunner.class)
public class TestSampleClass {
...
Or call the following in a #Before method:
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
See the MockitoAnnotations and MockitoJUnitRunner JavaDocs for more information on the two approaches.
You can annotate your Object with #Mock, so its look like this
#Mock
DBproperties dbProperties;#Before public void init(){ MockitoAnnotations.initMocks(this);
}