I am writing a test case using JUnit for a method that takes an ENUM in the switch statement.
This is the method to be tested.
public <T extends BaseServiceResponse> T postProcess(T response,
ClientResponse clientResponse) throws EISClientException {
List<Message> messages = response.getMessages();
if(messages==null || messages.size()==0) {
return response;
}
Map<String, Message> messagesMap = populateMessages(response.getMessages());
ConditionOperator condition = getCondition();
switch(condition) {
case OR:
checkORCondition( messagesMap );
break;
case AND:
checkANDCondition( messagesMap );
break;
}
return response;
}
What I've done so far is:
#Test
public void testPostProcess() throws Exception {
clientResponse = mock(ClientResponse.class);
RetrieveBillingServiceResponse response = new RetrieveBillingServiceResponse();
BillingOverview billingOverView = new BillingOverview();
Message message = new Message();
message.setMessageCode("200");
message.setMessageType(MessageTypeEnum.MESSAGE_TYPE_INFO);
message.setMessageText("Service completed successfully");
response.setEntity(billingOverView);
response.setMessages(Arrays.asList(message));
MessageToExceptionPostProcessFilter postProcessFilter = new MessageToExceptionPostProcessFilter();
RetrieveBillingServiceResponse serviceResponse = postProcessFilter.postProcess(response, clientResponse);
assertEquals("200", serviceResponse.getMessages().get(0).getMessageCode());
I am getting a NullPointerException for conditonOperator which is of type ENUM and this holds only two members OR and AND which are the cases in the switch statement.
Can someone help me out how should I proceed with this test.
Thanks
Enum variables can be null. The getCondition() method is returning null. Why it's returning null, we can't really guess without seeing code you haven't shown us.
If getCondition() is private method you cannot mock it. If it is public method, you can mock it or if you have a setCondition, you can directly set the ENUM.
Assuming if you are using Mockito or PowerMock or EasyMock you can use something like
when(postProcessFilter.getCondition()).thenReturn(Enum.OR);
Related
I got a AssertionError when I execute the unit test. response.getBody() is null.
Here is unit test method;
public void when_CustomerNumNotNull_Expect_TspResult() {
/*
some code
*/
TspResultDto tspResultDto = new TspResultDto();
tspResultDto.setTspResult("blabla");
Mockito.doReturn(tspResultDto).when(creditService)
.getTspResult(tspInputDto);
ResponseEntity<TspResponse> response = creditController
.getTspResult(TspRequest);
Assert.assertNotNull(response.getBody()); // error occured this line because body null.
Assert.assertEquals(HttpStatus.OK, response.getStatusCode());
//Assert.assertEquals(true, response.getBody().isHrResult());
}
}
TspInputDto and TspRequest are my model Class.
But I don't get an error when I run it with a single parameter like below without needing the model class.
Mockito.doReturn(newCreditApplicationDto).when(creditService)
.getNewCreditApplicationNo(customerNum);
ResponseEntity<NewCreditApplicationResponse> response = creditController
.getNewCreditApplicationNo(customerNum);
Assert.assertNotNull(response.getBody());
Assert.assertEquals(HttpStatus.OK, response.getStatusCode());
Here is controller;
public ResponseEntity<TspResponse> getTspResult(
TspRequest tspRequest) {
TspInputDto tspInputDto = creditDemandRestMapper
.toTspInputDto(tspRequest);
TspResultDto tspResultDto = creditService
.getTspResult(tspInputDto);
TspResponse tspResponse = creditDemandRestMapper
.toTspResponse(tspResultDto);
return new ResponseEntity<>(tspResponse, HttpStatus.OK);
}
Here is service;
public TspResultDto getTspResult(
TspInputDto tspInputDto) {
TspResultDto tspResultDto = new TspResultDto();
/*
Some code here...
*/
return tspResultDto;
}
Where am I doing wrong?
In this line:
Mockito.doReturn(tspResultDto).when(creditService)
.getTspResult(tspInputDto);
you set the mock to return your tspResultDto object if the argument equals() to tspInputDto, meaning it should be an equal object (in terms of equals() comparison). Probably your TspInputDto class doesn't have equals method defined properly.
Anyways, I'd propose to rewrite this line of code using argThat matcher:
Mockito.doReturn(tspResultDto).when(creditService)
.getTspResult(ArgumentMatchers.argThat(tspInputDto ->
// condition for provided tspInputDto
));
Have you mocked the creditController? If you haven't then it will not give you response mock object.
When I used Powermock to mock a private method, and then verify it in another method's unit test, to check if it was called and with correct times. But I found I can verify whether the method was called and with the correct param, the called times of the method can be any number, however the unit test always passed. If someone can help me solve the problem. thx!
This is my source code:
public enum ConversionCommon{
INSTANCE;
...
public void getConvertTypeData(JSONObject result, JSONObject conversionData, String intent){
String uncertainty = "";
String unit1 = "";
String unit1_char = "";
if(result.has(ConversionDefine.CONVERSION_UNCERTAINTY)){
uncertainty = result.getString(ConversionDefine.CONVERSION_UNCERTAINTY);
}
if(result.has(ConversionDefine.CONVERSION_UNIT1)){
unit1 = result.getString(ConversionDefine.CONVERSION_UNIT1);
}
if(result.has(ConversionDefine.CONVERSION_UNIT1_CHAR)){
unit1_char = result.getString(ConversionDefine.CONVERSION_UNIT1_CHAR);
}
setUnitCount(conversionData, uncertainty, intent);
setDestUnits(conversionData, unit1, unit1_char);
}
}
The method getConvertTypeData() calls two methods once. The follow is my test case code:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ ConversionCommon.class, LengthConversion.class })
#PowerMockIgnore("javax.management.*")
public class ConversionCommonTest{
#Before
public void setUp() throws Exception{
PowerMockito.mockStatic(LengthConversion.class);//
PowerMockito.spy(LengthConversion.class); //
}
#Test
public void should_getConvertTypeData_invoke_setUnitCount() throws Exception{
JSONObject result = new JSONObject();
JSONObject conversionData = new JSONObject();
result.put(ConversionDefine.CONVERSION_UNCERTAINTY, "3");
result.put(ConversionDefine.CONVERSION_UNIT1, "meter");
result.put(ConversionDefine.CONVERSION_UNIT1_CHAR, "centmeter");
suppress(method(ConversionCommon.class, "setUnitCount", JSONObject.class, String.class, String.class));
ConversionCommon.INSTANCE.getConvertTypeData(result, conversionData, ConversionDefine.INTENT_LENGTH_CONVERSION);
PowerMockito.verifyPrivate(ConversionCommon.INSTANCE, Mockito.times(1)).invoke("setUnitCount", Mockito.anyObject(), Mockito.anyString(), Mockito.anyString());
}
The test case can run successful but if I change the last line to ...
PowerMockito.verifyPrivate(ConversionCommon.INSTANCE, Mockito.times(100)).invoke("setUnitCount", Mockito.anyObject(), Mockito.anyString(), Mockito.anyString());
... and re-run the test case. The result is also passed. But in fact I only call the method setUnitCount only once in Refo.
The edition of test framework: mockito:1.10.19;powermock:1.6.5
How can I correct verify the private method's call times with the API PowerMockito.verifyPrivate();
You are doing right, except one thing. You're spying on enum constant. And each enums constant is separate inner class. So you have to add two things:
Enum constant to #PrepareForTest with using fullyQualifiedNames, like `#PrepareForTest(values = { ConversionCommon.class, LengthConversion.class }, fullyQualifiedNames = "com.somepackage.ConversionCommon$INSTANCE")
Create a spy for instance: PowerMockito.spy(ConversionCommon.INSTANCE)
Replace constant with spy: Whitebox.setInternalState(ConversionCommon.class, spy)
Now, you can stub the spy method as usual doNothing().when(spy, "setUnitCount");
Code snippet for some abstract singleton implement via enum:
enum
public enum Singleton {
INSTANCE;
public void doSomething(){
callPrivateMethod();
}
private void callPrivateMethod() {
}
}
test
RunWith(PowerMockRunner.class)
#PrepareForTest(value = Singleton.class, fullyQualifiedNames = "com.stackoverflow.q46212600.Singleton$INSTANCE")
public class ClassUseSingletonTest {
#Test
public void should_verify_enum_method() throws Exception {
final Singleton spy = PowerMockito.spy(Singleton.INSTANCE);
Whitebox.setInternalState(Singleton.class, spy);
doNothing().when(spy, "callPrivateMethod");
new ClassUseSingletone().doSomething("do");
PowerMockito.verifyPrivate(Singleton.INSTANCE, times(1)).invoke("callPrivateMethod");
}
}
Full example, you may find here
I have actual method below:
public ResponseEntity<Message> catEnter(#PathVariable("catId") BigInteger catId, #RequestBody Catrequest catReq, HttpServletRequest request) throws CatDataException, InvalidCatExcecatption {
Message message = new Message();
try {
message = catManager.submitData(catReq.getMessage(), catId, request);
} catch (IOException e) {
throw new CatDataAppException(e.getMessage());
}
return (ResponseEntity<Message>) restResponse(message, request.getMethod());
// Getting null pointer exception in above line
}
I am using mockito for my test code as below:
#Test
public void submitData() throws Exception {
Message mes = new Message();
mes.setCode("00");
mes.setMessage("hi");
ResponseEntity<Message> responseentity = ((ResponseEntity<Message>) catController.catEnter(BigInteger.valueOf(3431), catRequest, mockRequest));
}
I'm getting null pointer exception, Message going as a null, even I set the value explicitly?
Here:
You pass mockRequest when making that call to your production code:
ResponseEntity<Message> responseentity = ... catController.catEnter(... mockRequest));
And your production call does:
return (ResponseEntity<Message>) restResponse(message, request.getMethod());
So the only conclussion: mockRequest is null!
So, first make sure that the passed variable is not null; like:
Request mockedRequest = mock(Request.class);
Or, use the #Mock annotation in case that mockedRequest is a field in your test class.
On top of that; you probably want to do some mock-specification, like:
when(mockedRequest.getMethod()).thenReturn( whatever )
But beyond that, you are lacking a lot of the fundamental basics of Java:
naming conventions: variable names go camelCase, like entityResponse. And typically, tests are named like testCatEnter to express the method that is tested.
You have casts ... where they are not required.
You have quite some code there ... that is unused, like the mes declaration in your test method.
Long story short: I have the feeling that you are overburdening yourself dramatically. First learn the basics; then go for the advanced Mockito stuff.
Below is the JUnit Test, oneLoginAuthUtil is Mocked. But Mockito.when is returning null. oneLoginAuthUtil.getMetaData is always null. Below is the code -
public void func() throws Exception {
StringBuilder b = new StringBuilder("test");
RequestContext context = new RequestContext();
Mockito.when(oneLoginAuthUtil.getMetaData(context, b)).thenReturn("abcdef");
ResponseEntity<Object> response = loginControllerImpl.handleGetMetaDataEndPointImpl(context);
}
public String getMetaData(RequestContext context, StringBuilder b) throws Exception {
Auth auth = getOneLoginAuthObject(context);
final Saml2Settings settings = auth.getSettings();
String metadata = settings.getSPMetadata();
List<String> errors = Saml2Settings.validateMetadata(metadata);
if (!errors.isEmpty()) {
b.append(errors.toString());
throw new SSOException("metadata_validation_error");
}
return metadata;
}
public ResponseEntity<Object> handleGetMetaDataEndPointImpl(RequestContext context) {
try {
StringBuilder b = new StringBuilder();
String metadata = oneLoginAuthUtil.getMetaData(context, b);
log.info(metadata);
return new ResponseEntity<>(metadata, new HttpHeaders(), HttpStatus.CREATED);
} catch (Exception e) {
return new ResponseEntity<>("<error>Exception: " + e.getMessage() + "</error>", new HttpHeaders(),
HttpStatus.CREATED);
}
}
But oneLoginAuthUtil.getMetaData method without StringBuilder as parameter works fine.
It returns null because when you mock a method using specific instances as parameters, Mockito will return the mapped return value if and only if the parameters provided while testing are equal to the parameters that you provided while mocking which is obviously not the case. Mockito did not have a match so it returns the default value for a method that returns an object called on a mock which is null.
In other words Mockito.when(oneLoginAuthUtil.getMetaData(context, b)) is equivalent to Mockito.when(oneLoginAuthUtil.getMetaData(Mockito.eq(context), Mockito.eq(b))), here as the class StringBuilder doesn't override the method equals(Object obj), the instance provided while mocking is not equal to the instance provided while testing as they are not the same instance (the only possibility to be equal when relying on the default implementation of equals(Object obj)) such that you get this behavior.
So you should use Mockito.any(StringBuilder.class) to match with any instances of type StringBuilder such that the instances don't need to be equal anymore, your code would then be:
Mockito.when(
oneLoginAuthUtil.getMetaData(Mockito.eq(context), Mockito.any(StringBuilder.class))
).thenReturn("abcdef");
Assuming that your main class is LoginControllerImpl and that it has a member field oneLoginAuthUtil of type OneLoginAuthUtil, you could use the annotation #InjectMocks to inject directly your mock of type OneLoginAuthUtil, the complete code would then be:
#RunWith(MockitoJUnitRunner.class)
public class LoginControllerImplTest {
#Mock
private OneLoginAuthUtil oneLoginAuthUtil;
#InjectMocks
private LoginControllerImpl loginControllerImpl;
#Test
public void func() throws Exception {
RequestContext context = new RequestContext();
Mockito.when(
oneLoginAuthUtil.getMetaData(
Mockito.eq(context), Mockito.any(StringBuilder.class)
)
).thenReturn("abcdef");
ResponseEntity<Object> response
= loginControllerImpl.handleGetMetaDataEndPointImpl(context);
...
}
}
StringBuilder does not implement equals() or hashCode(), so it can't be used for argument matching like that.
The problem really is that you shouldn't be passing a mutable object (such as StringBuilder) into your test subject. Why does returning "metadata" require you to append to a StringBuilder outside your scope?
I am new in writing the junit test cases and need help. I read about possible solutions but they are not working at this point.
Main class looks like below, which calls the method of ther class addResponseData(This method only sets values in session and returns nothing). Please see the code as per below.
#Test
public void testPublishData_Success() throws java.lang.Exception {
when(GetPropValues.getPropValue(PublisherConstants.ATMID)).thenReturn("ATM");
when(GetPropValues.getPropValue(PublisherConstants.DATA_SOURCE)).thenReturn("PCE");
ReadAndWriteFiles mockFiles = Mockito.mock(ReadAndWriteFiles.class);
PowerMockito.whenNew(ReadAndWriteFiles.class).withNoArguments().thenReturn(mockFiles);
Mockito.when(mockFiles.getAllFiles()).thenReturn(null);
KafkaProducer mockProducer = Mockito.mock(KafkaProducer.class);
PowerMockito.whenNew(ReadAndWriteFiles.class).withAnyArguments().thenReturn(mockProducer);
producer.publishData(null, "Test", "Data1");
}
ResponseWrapper signerResponse;
try {
privateClassObj.ensureDataLoaded(objSession); // Loads the required data into objSession)
signerResponse = new ResponseWrapper(ResponseType.SUCCESS);
signerResponse.addResponseData("signerList", objSession.getSignerList());
signerResponse.addResponseData("additionalSignerList", objSession.getAdditionalSignerList());
}
catch (ServiceException err) {
signerResponse = new ResponseWrapper(ResponseType.PARTIAL_SUCCESS);
}
return signerResponse;
}
TestClass: I have written junit test case as per below.
#Test
public void testSuccessfulCallWithSigners() {
List<Signer> signerList = setSignerList();
List<Signer> additionalSignerList = setSignerList();
when(objSession.getSignerList()).thenReturn(signerList);
when(nsbSession.getAdditionalSignerList()).thenReturn(additionalSignerList);
ResponseWrapper output = signerController.getUsers(request); // actual method call
assertEquals(output, responseWrapper);
}
This test case is failing because, I always get empty signerList and additionalSignerList.(test case result is getAdditionalSignerList() method should return List) Please let me know what am I doing wrong here. Thanks in Advance. I am also posting my the code of setSignerList() in case if you want to see it for reference.
private List<Signer> setSignerList() {
List<Signer> signerList = new ArrayList<Signer>();
signerList.add(primarySigner); // primarySigner is mock object.
return signerList;
}
You have mocked objSession and also you have returned your empty list when these two methods get called by the test case.
when(....).thenReturn(....) is used to specify a condition and a return value (Stubbing) for this condition.As you have mocked it and return your desired list using stubbing, it will not return the list returned by actual call.
List<Signer> signerList = setSignerList(); // EMPTY LIST
List<Signer> additionalSignerList = setSignerList(); // EMPTY LIST
when(objSession.getSignerList()).thenReturn(signerList); //MOCK
when(nsbSession.getAdditionalSignerList()).thenReturn(additionalSignerList); // MOCK