I am writing a JUnit test case for my code, but the Mockito is always returning null
#Component
public class ConnectorImpl {
public String returnString(String inte) {
String x = testing();
return x;
}
public String testing() {
return "test";
}
}
Test class
#RunWith(MockitoJUnitRunner.class)
public class ConnectorImplTest {
#Mock public ConnectorImpl connector;
#Test
public void testLoggedInRefill() throws Exception {
Mockito.when(connector.testing()).thenReturn("test");
String x = connector.returnString("8807");
assertEquals("8807", x);
}
}
When I am calling connector.returnString("8807");, it is always returning null. Is there anything I am doing wrong? I am new to JUnit.
One way you can test your method returnString is as :
// mock 'returnString' method call
Mockito.when(connector.returnString(anyString()).thenReturn("test");
// assert that you've mocked succesfully
assertEquals("test", connector.returnString("8807"));
According to your code, you are mocking your ConnectorImpl
So it is an empty object and it means that it is up to you to specifically when(...).then(...) any functionality that you like to test.
BTW - if you are testing the ConnectorImpl then you should not mock it, but actually use the real bean. You should mock the beans that ConnectorImpl is using.
So I would suggest your code look maybe like that:
#RunWith(MockitoJUnitRunner.class)
public class ConnectorImplTest {
public ConnectorImpl connector = new ConnectorImpl(...);
#Test
public void testLoggedInRefill() throws Exception {
String x = connector.returnString("8807");
assertEquals("8807", x);
}
}
You are mocking the object and you do not specify any behaviour for the returnString method of the mocked object. As you did for testing(), you can do the same for returnString() method:
when(connector.returnString(anyString())).thenReturn("text")
On the other hand why do you need ti mock this class?
Related
I don't want to use powermock anymore. Because junit5 started mocking static classes. So i am trying to get rid of powermock methods.
As you know, you can create an instance of a class with whenNew keyword. So i decided to use " mockConstruction " . But mockConstruction does not return the mocked object. It doesn't go inside the try block.
This is my BeforeEach method:
#BeforeEach
void setUp() {
partUnlinkService =
spy(new PartVideoUnlinkService(part1, part2,
part3));
}
This is my test method:
#Test
void shouldThrowException() throws Exception {
//given
UrlLinkDto urlLinkDto =
UrlPartLinkDto.builder().callId("333").videoId("5555544").build();
ArgumentCaptor<UrlPartLinkDto> argumentCaptor = ArgumentCaptor.forClass(UrlPartLinkDto.class);
//when
try (MockedConstruction<ObjectMapper> ignoredVariable = mockConstruction(ObjectMapper.class,
(objectMapper, context) -> {
//then
partUnlinkService.unlink(urlLinkDto, false);
verify(partLogCheckService, times(1)).checkForExistingVideo(
urlLinkDto.getVideoId());
verify(objectMapper, times(1)).writeValueAsString(argumentCaptor.capture());
Throwable throwable =
catchThrowable(() -> objectMapper.writeValueAsString(argumentCaptor.capture()));
assertThat(throwable).isInstanceOf(JsonProcessingException.class);
})) {
}
}
Any help would be appreciated.
You can access mocks that were created during the instantiation of your objects via MockedConstruction.constructed() method. It represents a collection of mocks that are created after each constructor's execution. If your object will be instantiated 3 times MockedConstruction<T>.constructed() will return 3 different mock objects for each instantiation.
According to documentation MockedConstruction<T>
Represents a mock of any object construction of the represented type.
Within the scope of the mocked construction, the invocation of any
interceptor will generate a mock which will be prepared as specified
when generating this scope. The mock can also be received via this
instance.
Simple implementation with comments below shows how to get mocks from MockedConstruction and verify them:
public class A {
private final String test;
public A(String test) {
this.test = test;
}
public String check() {
return "checked " + this.test;
}
}
public class TestService {
public String purchaseProduct(String param) {
A a = new A(param);
return a.check();
}
}
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedConstruction;
import org.mockito.Mockito;
import static org.mockito.Mockito.*;
public class ConstructorMockTest {
private MockedConstruction<A> mockAController;
#BeforeEach
public void beginTest() {
//create mock controller for all constructors of the given class
mockAController = Mockito.mockConstruction(A.class,
(mock, context) -> {
//implement initializer for mock. Set return value for object A mock methods
when(mock.check()).thenReturn(" Constructor Mock A ");
});
}
#Test
public void test() {
//each instantiation of class A will return new mock, which initialized by initializer from beginTest method
//new mock will be stored to mockAController.constructed() collection of mocks
A aObject = new A("test");
//ensure that method check() returns mocked value
Assertions.assertEquals(aObject.check(), " Constructor Mock A ");
//get just created mock for class A from controller. It will be first element of mockAController.constructed() collection
A aMock = mockAController.constructed().get(0);
//ensure that we get correct mock from mock controller, that it is equal from new created object
Assertions.assertEquals(aMock, aObject);
//verify that check method was executed on Mock
verify(aMock, times(1)).check();
//create new A object, new mock created and stored to mockAController.constructed()
A aObject2 = new A("test");
//ensure that method check() returns mocked value
Assertions.assertEquals(aObject2.check(), " Constructor Mock A ");
//get just created mock for class A from controller, it will be second object from constructed collection
A aMock2 = mockAController.constructed().get(1);
//ensure that we get correct mock from mock controller, that it is equal from just created A object
Assertions.assertEquals(aObject2, aMock2);
//verify that check method was executed on Mock
verify(aMock2, times(1)).check();
//Example of testing service which creates A object
TestService service = new TestService();
String serviceResult = service.purchaseProduct("test");
//ensure that service returned value from A mock
Assertions.assertEquals(serviceResult, " Constructor Mock A ");
//get just created mock for class A from controller, it will be third object from constructed collection
A aMock3 = mockAController.constructed().get(2);
//verify that check method was executed on Mock
verify(aMock3, times(1)).check();
}
#AfterEach
public void endTest() {
mockAController.close();
}
}
Let's rewrite your test. I do not have the full code, but I will try to create an example with comments:
#Test
void shouldThrowException() throws Exception {
//given
UrlLinkDto urlLinkDto =
UrlPartLinkDto.builder().callId("333").videoId("5555544").build();
ArgumentCaptor<UrlPartLinkDto> argumentCaptor = ArgumentCaptor.forClass(UrlPartLinkDto.class);
try (MockedConstruction<ObjectMapper> objectMapperMockedConstruction = mockConstruction(ObjectMapper.class,
(objectMapper, context) -> {
//initialize ObjectMapper mock to throw exception when argumentCaptor will come to writeValueAsString method
doThrow(JsonProcessingException.class).when(objectMapper).writeValueAsString(argumentCaptor.capture());
})) {
//execute service for testing and catch exception
Throwable throwable = catchThrowable(() -> partUnlinkService.unlink(urlLinkDto, false));
//verify that inner service was executed
verify(partLogCheckService, times(1)).checkForExistingVideo(urlLinkDto.getVideoId());
//verify that ObjectMapper was instantiated
Assertions.assertEquals(1, objectMapperMockedConstruction.constructed().size());
//get mock of ObjectMapper which was instantiated during service execution
ObjectMapper objectMapper = objectMapperMockedConstruction.constructed().get(0);
//verify that writeValueAsString was executed
verify(objectMapper, times(1)).writeValueAsString(argumentCaptor.capture());
//check that exception is correct
assertThat(throwable).isInstanceOf(JsonProcessingException.class);
}
}
I think I have the same question as you, hope someone can solve our problem.
In my case, I also want to got a return object like PowerMock.whenNew().withArguments().thenReturn(someThing), I try a lot of times but it failed.
I think mockConstruction just only can mock their behavior, can't verify their result like powerMock, and I couldn't find any articles or answers.
below is my post link :
Junit 5 use mockConstruction().withSetting().useConstructor() instead of PowerMock.whenNew().withArguments()
I am mocking 2 classes in one of my unit tests, defining the behavior with Mockito. When and then calling the functions.
One of the mocked classes works exactly as expected, the other returns null. I can't figure out what the difference is between the two.
QueryServiceTest.java
#Import({ QueryServiceTestConfig.class })
#RunWith(SpringRunner.class)
public class QueryServiceTest {
#Autowired
private QueryService queryService;
#MockBean
private ElasticConnectionService elasticConnectionService;
#MockBean
private HBaseConnectionService hbaseConnectionService;
#Test
public void test_getRecordsFromQuery() throws IOException {
// creation of sample data for inputs and outputs goes here
// This mock works when called from queryService.getRecordsFromQuery()
when(elasticConnectionService.getRowIdsFromQuery(filterParams, testIndex)).thenReturn(getRowIdsFromQuery_result);
List<JSONObject> matches = queryService.getMatchingRowIds(getRowIdsFromQuery_result);
// matchesArray is directly defined to make sure its exactly the same as in queryService.getRecordsFromQuery()
JSONObject matchesArray = new JSONObject("{\"testTable\":[\"testUUID\"]}");
// This mock fails when called from queryService.getRecordsFromQuery()
when(hbaseConnectionService.getRowsByIDs(matchesArray)).thenReturn(getRowsByIDs_result);
// This returns getRowsByIDs_result as expected
JSONArray test = hbaseConnectionService.getRowsByIDs(matchesArray);
// This returns null
JSONArray actual = new JSONArray(queryService.getRecordsFromQuery(filterParams, testIndex));
}
}
QueryService.java
#Service
public class QueryService {
#Autowired
private ElasticConnectionService elasticConnectionService;
#Autowired
private HBaseConnectionService hbaseConnectionService;
#Autowired
private PSQLConnectionService psqlConnectionService;
public String getRecordsFromQuery(
Map<String,String> filterParams,
String tablename) throws IOException {
/**
* Get records that match simple key/value filters
*/
// This mocked method returns exactly what was expected
List<List<JSONObject>> lookupsList = elasticConnectionService.getRowIdsFromQuery(filterParams, tablename);
List<JSONObject> matches = getMatchingRowIds(lookupsList);
// matchesArray is exactly the same as in the test class
JSONObject matchesArray = new JSONObject("{\"testTable\":[\"testUUID\"]}");
// This returns null
JSONArray hbResults = hbaseConnectionService.getRowsByIDs(matchesArray);
return hbResults.toString(4);
}
}
QueryServiceTestConfig.java
#Configuration
public class QueryServiceTestConfig {
#Bean
public QueryService queryService() {
return new QueryService();
}
#Bean
public ElasticConnectionService elasticConnectionService() {
return new ElasticConnectionService();
}
#Bean
public HBaseConnectionService hbaseConnectionService() {
return new HBaseConnectionService();
}
#Bean
public PSQLConnectionService psqlConnectionService() {
return new PSQLConnectionService();
}
}
What confuses me most is that in queryService.getRecordsByQuery(), the elasticConnectionService.getRowIDsFromQuery() mock returns what was expected, but the hbaseConnectionService.getRowsByIDs() mock returns null.
The elastic and hbase connection service classes are both defined in the same folder and the only annotation they have is #Service. I would think I had configured something wrong if both failed, but the fact that the elasticConnectionService call works as expected tells me something else is happening.
If the package of JSONObject is org.json, JSONObject's equals method looks like:
public boolean equals(Object object) {
return object == null || object == this;
}
Since the instance of matchesArray in QueryService is different than the instance in QueryServiceTest, the equals() method will return false.
Try changing this:
when(hbaseConnectionService.getRowsByIDs(matchesArray)).thenReturn(getRowsByIDs_result);
to this, and see if your results change:
when(hbaseConnectionService.getRowsByIDs(Mockito.any())).thenReturn(getRowsByIDs_result);
I think you also may be able to do this:
when(hbaseConnectionService.getRowsByIDs(Mockito.eq(matchesArray))).thenReturn(getRowsByIDs_result);
or:
when(hbaseConnectionService.getRowsByIDs(Matchers.eq(matchesArray))).thenReturn(getRowsByIDs_result);
Because under the hood, the Matchers.eq() method probably calls JSONObject.equals(), the Matcher probably won't work (I didn't check the source code for Matchers.eq()).
In general, when setting up a mock method call, you want to wrap your parameter(s) in one of Mockito's Matcher's methods. Unfortunately, that won't work in your scenario.
(Note that the class Mockito extends Matchers)
I'm seeing a different in behaviour when spying on a service using the #Spy annotation and having Mockito create the Server verses explicitly calling the constructor.
public class MyService {
private final Supplier<String> methodBCall;
public MyService() {
methodBCall = this::methodB;
}
public void methodA() {
methodBCall.get();
}
public String methodB() {
return "methodB";
}
}
#RunWith(MockitoJUnitRunner.class)
public class MyTest {
#Spy
private MyService myService1;
#Spy
private MyService myService2 = new MyService();
#Test
public void testSucceeds() {
myService1.methodA();
verify(myService1, times(1)).methodA();
verify(myService1, times(1)).methodB();
}
#Test
public void testFails() {
myService2.methodA();
verify(myService2, times(1)).methodA();
verify(myService2, times(1)).methodB();
}
}
The failing test fails with
Wanted but not invoked:
myService2.methodB();
-> at com.phemi.services.policy.impl.MyTest.testFails
Why do these two behave differently? What is Mockito doing to initialize myService1 that enables it to spy on methodB?
This is a simplified example, in my case to test my service properly I need to call its constructor with an argument (and so cannot use the #Spy with a default constructor). However, when I do that I cannot properly verify method calls.
The spy on myService2 is only created after the object has been constructed, so having a method call in the constructor is not helpfull as it contains a method reference to the initial object (which is not the spy object).
The difference becomes more evident when you compare the implementation for both cases:
Mockito.spy(Class)
public static <T> T spy(Class<T> classToSpy) {
return MOCKITO_CORE.mock(classToSpy, withSettings()
.useConstructor()
.defaultAnswer(CALLS_REAL_METHODS));
}
Mockito.spy(Object)
public static <T> T spy(T object) {
return MOCKITO_CORE.mock((Class<T>) object.getClass(), withSettings()
.spiedInstance(object)
.defaultAnswer(CALLS_REAL_METHODS));
}
As you can see the first case, based on a class (which is used if no instance for #Spy was created), creates a mock first and uses the constructor on the mocked object.
In the second case the constructor is not considered instead a different instance is created.
Is it possible to test that the "innerMethod" was called without modifying the Class class?
I need to make a unit test in a separate class both scenario of the "someCondition".
The problem is that the method is void so I cannot make use of the return type. The only way would be to check if the "innerMethod" was called.
I was thinking to use Mokito verify but this method is called inside a method on an object created at runtime.
Any suggestion is most welcome.
public class Class {
public void outerMethod(outerObj) {
if(someCondition) {
Object innerObj = new Object();
innerObj.innerMethod(outerObj);
} else {
//other code
}
}
You can achieve that with the use of Mockito::times and Mockito::verify methods.
test setup would be as follows:
#InjectMocks
private SomeService service;
#Mock
private SomeHelper helper;
and then test that some method from the helper has been involved in the following manner:
#Test
public void testInnerHasBeenCalledOnce() throws Exception {
service.outherMethodName(someParam);
Mockito.verify(helper, Mockito.times(1)).innerMethodName(someParamSecond);
}
I have a method validate for which i need to write junit test cases
public List<Field> validate(){
final Future<Map<ObjectId, Field>> uniqueResult = globalUniqValidator.execute(uniqueValidations,
validationContent.getEvalFieldValueMap(), inputFieldValuesMap);
final Future<Map<ObjectId, Field>> subnetResult = globalSubnetValidator.execute(subnetValidations,
validationContent.getEvalFieldValueMap(), inputFieldValuesMap, surveyTemplateRefId);
}
it has two methods which returns future object
#RunWith(MockitoJUnitRunner.class)
public class GlobalValidationServiceTest {
#Mock
private Future<Map<ObjectId, Field>> future;
#Test
public void validateGlobalValidation() throws Exception {
given(globalUniqValidator.execute(uniqueValidations, validationContent.getEvalFieldValueMap(), inputFieldValuesMap)).willReturn(future);
when(future.get()).thenReturn(inputFieldValuesMap);
given(globalSubnetValidator.execute(globalValidation, evalFieldValueMap, inputFieldValuesMap, surveyTemplateRefId)).willReturn(future);
when(future.get()).thenReturn(inputFieldValuesMap_subnet);
}
however when I debug I get a null for both uniqueResult and subnetResult
i guess it is not being mocked
it also says unused mock at the lines where the mock is written
Am I missing something ?