Unable to inject mocks for my jersey project - java

I'm very new to writing unit tests for java. I want to write a test for method1:
public ClassA {
public String method1() {
ClassB classInst = ClassB.getInstance()
return classInst.doSomething()
}
}
Here, doSomething in classB connects to some databases and does an operation. This is my test class:
public TestClassA {
#Mock
private ClassB classBInst = mock(ClassB.class)
#InjectMocks
private ClassA classAInst = new ClassA()
#Before
public void setup() {
when(classInst.isClientEnabled()).thenReturn("ReturnStr");
}
#Test
public void testMethod1() {
String result = classAInst.method1();
assertEquals(result, "ReturnStr")
}
}
But the assert is failing because ClassB.doSomething() is not returning the mocked return value. Am I doing something wrong here? What is the correct way to mock classB here? I am using junit4 and mockito here

Related

Use result of one mock call in another

How can I use/inject the result of one mock into another?
I think I did it in the wrong way
The int param is always null
I use spy because the method I test is void.
Can I do it using mockito?
#RunWith(MockitoJUnitRunner.class)
public class Test {
#Mock
Utils utils;
#Mock
Custom custom;
#Spy
#InjectMocks
MyService service;
#Test
public void test(){
Mockito.when(utils.get("p")).thenReturn(1); //use result of it in the next mock call
Mockito.when(custom.isValid(1)).thenReturn(true); //custom use 1 here
Mockito.doCallRealMethod().when(service).doIt("p");
service.doIt("p");
Mockito.verify(service,Mockito.times(1)).doIt("p");
}
}
#Service
public class MyService {
Utils utils;
Custom custom;
public MyService(Utils utils) {
this.utils = utils;
}
public void doIt(String value){
int param = utils.get(value);
if(custom.isValid(param)){
//do it
}
}
}
You don't actually need to Spy MyService. You can simplify your test and get it to work:
#RunWith(MockitoJUnitRunner.class)
public class Test {
#Mock
Utils utils;
#InjectMocks
MyService service;
#Test
public void test(){
// Arrange
Mockito.doReturn(1).when(utils.get("p"));
Mockito.when(custom.isValid(1)).thenReturn(true);
// Act
service.doIt("p");
// Assert
Mockito.verify(utils, Mockito.times(1)).get("p");
// You should also confirm that whatever is done in `if(param==1)` is actually done
}
}
You're mocking with wrong parameter, change your test like that:
public class Test {
#Mock
Utils utils;
#InjectMocks
MyService service;
#BeforeEach
void setUp(){
initMocks(this);
}
#Test
public void test(){
Mockito.when(utils.get(any())).thenReturn(1);
service.doIt("p");
Mockito.verify(utils).get(any());
}
}
Instead any() you can put any another variable but it should be the same variable with variable which you call the service

PowerMockito null pointer when trying to use ApplicationContext

I have a class name ServiceLocator
public class ServiceLocator implements ApplicationContextAware {
private transient ApplicationContext _applicationContext;
private static ServiceLocator _instance = new ServiceLocator();
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
_instance._applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return _instance._applicationContext;
}
public static Object findService(String serviceName) {
return _instance._applicationContext.getBean(serviceName);
}
}
I am trying to use that class to find Service into Approver class methods
public class ApproverService extends AbstractDataService implements IApproverService {
public void updateCompletedInboxStatus(String status) {
IInboxService inboxService = (IInboxService)ServiceLocator.findService("inboxService");
InboxItem inboxItem = inboxService.getInboxItem("test");
inboxItem.setWorkItemStatus(status);
inboxService.saveInboxItem(inboxItem);
}
}
With that code i am trying to write Junit with PowerMockRunner
#RunWith(PowerMockRunner.class)
#PrepareForTest({ApproverService.class})
public class ApproverServiceTest {
#InjectMocks
ApproverService approverService;
#Mock
IInboxService inboxService;
#Mock
ServiceLocator serviceLocator;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void updateCompletedInboxStatus() {
RequestAccessHeader reqHdr = new RequestAccessHeader();
reqHdr.setRequestStatus(AccessConstants.REQ_STATUS_HOLD_INT);
String status = "test";
PowerMockito.mockStatic(ServiceLocator.class);
when(serviceLocator.findService("inboxService")).thenReturn(inboxService);
approverService.updateCompletedInboxStatus(status);
}
}
But I am getting null pointer
java.lang.NullPointerException
at com.alnt.fabric.common.ServiceLocator.findService(ServiceLocator.java:25)
at com.alnt.access.approver.service.ApproverServiceTest.updateCompletedInboxStatus(ApproverServiceTest.java:80)
Please help me to find the solution for that issue.
The static method is obviously not mocked.
The problem is most probably because you haven't add the to-be-mocked class in #PrepareForTest
Change it to #PrepareForTest({ApproverService.class, ServiceLocator.class})
Off-topics:
Although it compiles, calling static method by instance reference is not a good practice. Therefore the line should be when(ServiceLocator.findService(...)).thenReturn(inboxService).
Another problem is, you tried to use Singleton pattern but in wrong way. A singleton is suppose to return you an instance so the caller can call its instance method. Your findService is preferably an instance method and to be called as ServiceLocator.getInstance().findService(...). To further improve, unless you really need it to be a singleton, you should make it a normal object instance and inject to objects that need it (given you are already using Spring, I see no reason making a Singleton)
The setup for the static method is not mocked correctly
#RunWith(PowerMockRunner.class)
#PrepareForTest({ServiceLocator.class}) //Prepare static class for mock
public class ApproverServiceTest {
#Mock
IInboxService inboxService;
#Mock
InboxItem item;
#InjectMocks
ApproverService approverService;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void updateCompletedInboxStatus() {
//Arrange
String status = "test";
PowerMockito.mockStatic(ServiceLocator.class);
when(ServiceLocator.findService("inboxService")) //<-- NOTE static call
.thenReturn(inboxService);
when(inboxService.getInboxItem("test")).thenReturn(item);
//Act
approverService.updateCompletedInboxStatus(status);
//...
}
}
Reference Mocking Static Method
The subject under test should actually be refactored to avoid the service locator anit-pattern / code smell and should follow explicit dependency principle via constructor injection.
public class ApproverService extends AbstractDataService implements IApproverService {
private IInboxService inboxService;
#Autowired
public ApproverService(IInboxService inboxService){
this.inboxService = inboxService;
}
public void updateCompletedInboxStatus(String status) {
InboxItem inboxItem = inboxService.getInboxItem("test");
inboxItem.setWorkItemStatus(status);
inboxService.saveInboxItem(inboxItem);
}
}
That way the subject class is genuine about what it needs to perform its function correctly,
And the test can then be refactored accordingly
#RunWith(PowerMockRunner.class)
public class ApproverServiceTest {
#Mock
IInboxService inboxService;
#Mock
InboxItem item;
#InjectMocks
ApproverService approverService;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void updateCompletedInboxStatus() {
//Arrange
String status = "test";
when(inboxService.getInboxItem("test")).thenReturn(item);
//Act
approverService.updateCompletedInboxStatus(status);
//...
}
}

First mock of the method applied always

I want to test a few cases in a method by mocking external dependency to return different results for every test case. But when always returns what is defined at first time (in this example - empty set) and that brokes the next tests.
If I run tests one by one they pass successfully but when I run the whole class only the first test pass and others fail.
Testing class:
class ExampleTest {
#Mock
private Dao dao;
#Mock
private Validator validator;
#Spy
#InjectMocks
Controller controller;
#BeforeEach
void setUp() {
initMocks(this);
}
private final static Set DATA = Set.of("data1", "data2");
#Test
void firstTest() throws UserDashboardException, DashboardException, WidgetException {
when(validator.filter(DATA)).thenReturn(Collections.emptySet());
assertThrows(Exception.class, () -> controller.create(DATA));
}
#Test
void secondTest() throws UserDashboardException, DashboardException, WidgetException {
when(validator.filter(DATA)).thenReturn(DATA);
controller.create(DATA);
verify(dao, times(1)).create(eq(DATA));
}
}
Tested class:
public class Controller {
private Dao dao;
private Validator validator;
public Controller(Dao dao,Validator validator) {
this.dao = dao;
this.validator = validator;
}
public String create(Set<String> data) {
data = validator.filter(data);
if (data.isEmpty()) {
throw new Exception("Invalid data.");
}
return dao.create(data);
}
}
So, in both tests create method throws an exception which is not what I expect. Maybe I miss some point?
Have you tried with doReturn method?
doReturn(DATA).when(validator).filter(DATA)
which can be import from org.mockito.Mockito.doReturn;
Edited: there might be a bug inside your code implementation:
data = validator.filter(data);

How can we mock a response from another class using Mockito while unit testing

I have a method to test which is calling another class to get some information:
public ClassToTest {
public void methodToTest() {
AnotherClass ac = Factory.getInstance();
ResponseObj response = ac.anotherMethod();
}
}
AnotherClass is part of another JAR and I would like to mock the response from it(to be specific mock ResponseObj response)
How can I achieve that using Mockito?
First you need is to make your class testable. It means you need to extract object creation (AnotherClass ac = Factory.getInstance()) from your methodToTest to instance field or maybe separate method (to be able to mock it), or even better - create object outside of your class and pass it via constructor. As a result, your class under test should look like:
public class ClassToTest {
private AnotherClass ac;
public ClassToTest(AnotherClass ac) {
this.ac = ac;
}
public void methodToTest() {
ResponseObj response = ac.anotherMethod();
response.smth();
}
}
Then you need to declare AnotherClass and ResponseObj as fields in test class, and initialize them as a mocks.
AnotherClass ac = Mockito.mock(AnotherClass.class);
ResponseObj responseMock = Mockito.mock(ResponseObj.class);
After that you can mock method call:
when(anotherClassMock.anotherMethod()).thenReturn(responseMock);
At the end your test class should look like:
public class ClassToTestTest {
private AnotherClass anotherClassMock = mock(AnotherClass.class);
private ResponseObj responseMock = mock(ResponseObj.class);
private ClassToTest classToTest = new ClassToTest(anotherClassMock);
#Test
public void test() {
when(anotherClassMock.anotherMethod()).thenReturn(responseMock);
classToTest.methodToTest();
verify(responseMock, only()).smth();
}
}
And in case you couldn't change public API of your ClassToTest, you can use approach with Mockito spy and protected method.
public class ClassToTest {
public void methodToTest() {
AnotherClass ac = constructAnotherClassObj();
ResponseObj response = ac.anotherMethod();
response.smth();
}
protected AnotherClass constructAnotherClassObj() {
return Factory.getInstance();
}
}
public class ClassToTestTest {
private AnotherClass anotherClassMock = mock(AnotherClass.class);
private ResponseObj responseMock = mock(ResponseObj.class);
private ClassToTest classToTest = spy(new ClassToTest());
#Test
public void test() {
when(anotherClassMock.anotherMethod()).thenReturn(responseMock);
when(classToTest.constructAnotherClassObj()).thenReturn(anotherClassMock);
classToTest.methodToTest();
verify(responseMock, only()).smth();
}
}
Although the answer by #arsen_adzhiametov is correct and up to the mark I would like to contribute how I do it.
In this case, I am mocking the value of HomeClient which internally is a WebClient that calls out another service for some values.
TestClass.java (Please name it better)
...
import org.mockito.Mockito;
...
class TestClass {
HomeClient mockHomeClient;
#BeforeEach
void setup() {
mockHomeClient = Mockito.mock(HomeClient.class);
// Axon specific test code. Can ignore if not using Axon.
fixture = new AggregateTestFixture<>(SomeAgreegate.class);
fixture.registerInjectableResource(mockHomeClient);
}
#Test
void testOpenOperation() throws HomeClientException {
Mockito.when(mockHomeClient.getXYZ("nice")).thenReturn(2);
// Do what you will with your code and call the method which you want to test
// Mockito will mock the `HomeClient` in this case and `getXYZ` will return `2`
// You can also change the mock response any time in the same function
Mockito.when(mockHomeClient.getXYZ("nice")).thenReturn(-100);
// Or specify different results on mock when different values are provided
Mockito.when(mockHomeClient.getXYZ("nice")).thenReturn(1);
Mockito.when(mockHomeClient.getXYZ("foo")).thenReturn(100);
Mockito.when(mockHomeClient.getXYZ("bar")).thenReturn(0);
}
}

How to tell a Mockito Mock annotation to return a mock object which is not null?

I am trying to unit test a method, which has different branches depending upon the value of an object that is created inside it. The below code demonstrates it.
public class AClass {
public void method2() {
//Some code goes here
}
public void method1(BClass bObject) {
C_Class cObject = bObject.someMethodThatReturnsC();
if(cObject != null) {
method2();
method2();
}
}}
Below is the TestClass:
public class AClassTest {
#InjectMocks
AClass AClassSpy;
#Mock
BClass b_objectMock;
#Mock
C_Class c_objectMock;
#BeforeMethod
public void beforeMethod() {
AClassSpy = spy(new AClass());
MockitoAnnotations.initMocks(this);
}
public void method1Test () {
doReturn(c_objectMock).when(b_objectMock).someMethodThatReturnsC());
AClassSpy.method1(b_objectMock);
verify(AClassSpy, times(2).method2();
}
}
However, it always FAILS, since the c_objectMock is always null. What do I do to tell Mockito to not to return a null object?
It works good, just use #Before annotation from junit, not #BeforeMethod, and mark your test method like #Test and remove second bracket from
doReturn(c_objectMock).when(b_objectMock).someMethodThatReturnsC())<-this one;
and add bracket at verify:
verify(AClassSpy, times(2)<-here.method2();
And just take care of your code!
This should work:
public class AClassTest {
#InjectMocks
private AClass AClassSpy;
#Mock
private BClass b_objectMock;
#Mock
private C_Class c_objectMock;
#Before
public void beforeMethod() {
AClassSpy = spy(new AClass());
MockitoAnnotations.initMocks(this);
}
#Test
public void method1Test() {
doReturn(c_objectMock).when(b_objectMock).someMethodThatReturnsC();
AClassSpy.method1(b_objectMock);
verify(AClassSpy, times(2)).method2();
}
}
Instead of before method you can use annotation #RunWith. It looks clearly:
#RunWith(MockitoJUnitRunner.class)
public class AClassTest {
#Spy
#InjectMocks
private AClass AClassSpy;
#Mock
private BClass b_objectMock;
#Mock
private C_Class c_objectMock;
#Test
public void method1Test() {
doReturn(c_objectMock).when(b_objectMock).someMethodThatReturnsC();
AClassSpy.method1(b_objectMock);
verify(AClassSpy, times(2)).method2();
}
}
You are having this behaviour because you are not mocking property the call to someMethodThatReturnsC.
It should be:
doReturn(c_objectMock).when(b_objectMock).someMethodThatReturnsC();

Categories

Resources