I have created a Junit test case in an existing class where I want to ignore few mocks
#InjectMock
private HomeService homeService;
#Mock
private HomeUtility homeUtility;
#Test
public void testIsFilterWorkedTrue() {
homeService.getData();
}
HomeService.java
class HomeService {
#Autowired
private HomeUtility homeUtility;
public [RETURN_TYPE] getData() {
// call mocked method
output = mockedMethodcall();
test = homeUtility.callMethod(output);
return test;
}
}
In the above code, for homeUtility.callMethod(output);, I don't want it to be mocked and should go inside the method. I have to use
#Mock
private HomeUtility homeUtility;
because it is getting used in other methods as well. How can I ignore it
You can use thenCallRealMethod for ensuring the actual method is called for that object.
#InjectMock
private HomeService homeService;
#Mock
private HomeUtility homeUtility;
#Test
public void testIsFilterWorkedTrue() {
when( homeUtility.callMethod(anyString()).thenCallRealMethod() )
homeService.getData();
}
You can also use spy for this. Some more reading: https://www.javabullets.com/mockito-partial-mocks-mock-and-spy/
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;
I have a JavaEE application with Stateless EJBs that I use for business logic (EjbBusiness) and database access (EjbDAO). I need to run a unit test on EjbBusiness, but the DAO method always returns zero.
In the example below I have both classes and the unit test. I mock the EjbDAO method that connects to the database, to return a testing SQL connection:
#Stateless
public class EjbDAO {
public Connection getConnFromPool() {
Connection conn = null; // in production this would return a connection
return conn;
}
public int add2(int i) {
Connection conn = getConnFromPool();
System.out.println("in EjbDAO: " + i);
return i + 2;
}
}
#Stateless
public class EjbBusiness {
#Inject
private EjbDAO dao;
public int add2(int i) {
int j = dao.add2(i);
System.out.println("in EjbBusiness: " + j);
return j;
}
}
Since I mock one of the methods of EjbDAO, I annotate it with #Spy in UnitTest:
#RunWith(MockitoJUnitRunner.class)
public class UnitTest {
#InjectMocks
private EjbBusiness biz;
#InjectMocks
#Spy
private EjbDAO dao;
#Before
public void setup() {
dao = Mockito.mock(EjbDAO.class);
biz = Mockito.mock(EjbBusiness.class);
MockitoAnnotations.initMocks(this);
}
#Test
public void testBean() {
// this would return the testing connection
Mockito.doReturn(null).when(dao).getConnFromPool();
int i = biz.add2(3);
assertThat(5).isEqualTo(i);
}
}
Problem is that the assertion doesn't work, as biz.add2(3) returns zero instead of 5. Also, the System.out.println in both beans is not printed. How to declare/mock the beans for the test to work?
Use #InjectMocks only when you calling actual method otherwise don't use it. And also don't use #InjectMocks and Mockito.mock() or #Mock together.
In your code you are using #InjectMocks on dao object and you are also creatign mock for that. And use Mockito.mock() when you want to stub the method calls instead of calling actual methods.
System.out.println() is not working in your code because you created mocks for objects biz and dao. Actual methods (i.e add2() because of this you are getting 0 as output) not executed when you call with mock objects.
For more info on when to use #InjectMocks refer
this
#RunWith(MockitoJUnitRunner.class)
public class UnitTest {
#InjectMocks
private EjbBusiness biz;
#Mock
private EjbDAO dao;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testBean() {
// this would return the testing connection
Mockito.doReturn(null).when(dao).getConnFromPool();
Mockito.doCallRealMethod().when(dao).add2(Mockito.anyInt());
int i = biz.add2(3);
assertThat(i).isEqualTo(5);
}
}
You should not use one unit test to test both classes.
You should have two test classes to test them.
For Example,
#RunWith(MockitoJUnitRunner.class)
public class EjbBusinessTest {
#InjectMocks
private EjbBusiness biz;
#Mock
private EjbDAO dao;
#Test
public void testAdd2() {
// this would return the testing connection
Mockito.doReturn(null).when(dao).getConnFromPool();
Mockito.doReturn(5).when(dao).add2();
int i = biz.add2(3);
assertThat(5).isEqualTo(i);
}
}
In the above class we are testing only the method EjbBusinessTest.add2 and we don't care what happens or if the method EjbDAO.add2 is working properly. In this all we should care is whether the method under test is working properly, hence we mock everything external to that method.
Following a similar approach for EjbDAO.add2 as well, The test case should look like something given below. I have also made the method EjbDAO.getConnection private so that that should also be included in the test. This choice should be made by you if you need to make it private or public. If you decide to keep it public then you should use #Spy on EjbDAO and mock the EjbDAO.getConnection method.
#RunWith(MockitoJUnitRunner.class)
public class EjbDAOTest {
//instantiate this object the way you want. Mock the external objects used inside this like the library used to get connection inside EjbDAO.getConnection() Method
#InjectMocks
private EjbDAO dao;
#Test
public void testAdd2() {
// I would suggest you to make the getConnection method private.
// do not mock the getConnection here, instead mock how you are getting the connection inside the getConnection method.
int i = dao.add2(3);
assertThat(5).isEqualTo(i);
}
}
Hope it helps.
As per my knowledge, We can Mock the private method in same class by using PowerMockito.
With in the same class is working fine for me , but when i'm calling private method from the other class it's not working.
Below Example i've 2 classes , Service class and Helper classes
Helper class having private method.
#RunWith(PowerMockRunner.class)
#PrepareForTest({ Helper.class,Service.class })
#PowerMockIgnore("javax.management.*")
public class EPartnerBatchServiceTest {
private Helper helper;
#InjectMocks
private ServiceClass serviceClass;
#Before
public void setUp() throws Exception {
helper = PowerMockito.spy(new Helper());
ServiceClass = PowerMockito.spy(new serviceClass());
MockitoAnnotations.initMocks(this);
}
#Test
public void testUpdateIndividualUserStatus() throws Exception {
PowerMockito.doReturn("Test").when(helper, "privateMethod", anyString(), Matchers.anyObject());
String response = serviceClass.update(loggerId, activityLogDTO);
}
}
Sample Classes :
Class A{
value=new B().method1();
}
Class B{
public method1(){
value = method2();
}
private method2(){
return "Test";
}
}
You shouldn't be worrying with testing explicitly your private methods, since they are not accessible for the ones calling it, it's function should be tested somewhere in the flow of your public methods. But, if for some reason you need to test them explicitly, then maybe reflections and setting those methods as accessible for testing may resolve your problem.
You'll find great examples here: https://www.baeldung.com/java-method-reflection
I am trying to test the following class using Mockito and JUnit :
public class A {
private SomeClass someObject;
private SomeImpClass someImpObject1;
private SomeImpClass2 someImpObject2;
public A(SomeImpClass someImpObject1, SomeImpClass2 someImpObject2){
someObject = makeNewObject(someImpObject1, someImpObject2);
}
public makeNewObject(SomeImpClass1 someImpObject1, SomeImpClass2 someImpObject2){
return new SomeObject(someImpObject1,someImpObject2);
}
public usingSomeObject(){
someObject.doSomething();
}
}
So, I wrote a Unit Test using Mockito and JUnit :
#RunWith(MockitoJUnitRunner.class)
public class ATest {
#Mock
SomeImpClass1 someImpObject1;
#Mock
SomeImpClass2 someImpObject2;
#Mock
SomeObject someObject;
#Spy
A a;
#Before
public void setUp() {
when(A.makeNewObject).thenReturn(someObject);
this.A = new A(this.someImpObject1, someImpObject2);
when(someObject.doSomething).thenReturn(something);
}
}
The Issue I am facing here is, although I have stubbed the function makeNewObject to return a Mocked object of SomeClass, the code flow is still going inside the fucntion (makeNewObject) and giving a null exception.
What Am I Doing Wrong ?
I have wasted a day behind this.
Not Very Fluent with Mockito.
You wont be able to achieve what you are aiming for with spying and stubbing.
This is because your aiming at stubbing a method used in a constructor.. but you cannot start stubbing once you created a concrete object and spy it.. can't be done..
I would suggest creating a private class inside the test class which extends your class under test, override the method invoked in the constructor and then use it in your tests:
#RunWith(MockitoJUnitRunner.class)
public class ATest {
#Mock
SomeObject someObjectMock;
A a;
#Before
public void setUp() {
this.a = new MyTest();
}
private class MyTest extends ATest{
#Override
public makeNewObject(SomeImpClass1 someImpObject1, SomeImpClass2 someImpObject2){
return someObjectMock;
}
}
Now you dont need to use spying and stubbing of it also as the overriden method is always returning what you expect in the test.
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.