How to mock object created in a mocked method? - unit-testing

I am trying to create a unit test to verify that a function is called within a function. However, I run into an error when I try to make a new object within the method.
Here is the code I am attempting to test:
protected void triggerOnCourseType(#NonNull final DateTime triggerTime,
#NonNull final AssociateWorkState currentState,
#NonNull final AssociateWorkState updatedState,
#NonNull final Optional<CourseType> courseTypeToTrigger) {
if (courseTypeToTrigger.isPresent()) {
try {
final String courseID = detectCourseID(domain, courseTypeToTrigger.get());
log.info(String.format("Here is find the courseID %s and courseTypeToTrigger %s related to employee %s",
courseID, courseTypeToTrigger.get().getCourseCategory(),
currentState.getEmployeeIdentifier().getEmployeeId()));
final Optional<EnrollmentIdentifier> identifier = enrollmentTriggerServiceErgoDao
.createEnrollmentForMBMV2(
new WarehouseId(currentState.getBuilding().getCode()),
currentState.getEmployeeIdentifier(), currentState.getProcessPath(), courseID);
log.info(String.format("we triggered!! CourseID: %s , EmployeeID: %s, building: %s, "
+ "identifier returned from AFT: %s", courseID,
currentState.getEmployeeIdentifier().getEmployeeId(),
currentState.getBuilding().getCode(), identifier.isPresent() ? identifier.get() : null));
final MetricTimer metricTimer = new MetricTimer();
metricsEmitter.emitCount("WorkState:" + currentState.getEmployeeIdentifier(),
metricType, currentState.getAssociateWorkStatus().getIndex(),
metricTimer.getSystemStartTimeMillis());
} catch (final RuntimeException e) {
associateWorkStateDao.saveState(currentState);
throw e;
}
}
}
The error occurs when I create the new WarehouseId(currentState.getBuilding().getCode()). The error is below, but there is code that checks to make sure the argument is not null when creating a WarehouseId. This is failing, the argument is null in the test case. I have created a rule that when getBuilding() is called, it returns a building.mI think the issue stems from the fact that I'm making a new object within a method, and I'm unable to mock it in the test case. Is this possible?
Here is my test case. I want to verify that emitCount(...) is called when triggerOnCourseType(...) is called :
#Test
public void handle_emitMetric(){
List<String> courseList = new ArrayList<>();
courseList.add(COURSE_ID);
courseList.add(COURSE_ID2);
when(associateWorkState.getEmployeeIdentifier()).thenReturn(employeeIdentifier);
when(associateWorkState.getBuilding()).thenReturn(building);
when(metricCourseType.getCourseIdList()).thenReturn(courseList);
when(enrollmentTriggerServiceErgoDao.createEnrollmentForMBMV2(any(WarehouseId.class), any(EmployeeIdentifier.class), any(ProcessPath.class), any(String.class))).thenReturn(Optional.of(mockEnrollmentIdentifier));
mbm2TriggerHandler.triggerOnCourseType(metricTime,
associateWorkState,
associateWorkState,
Optional.of(metricCourseType));
MetricTimer metricTimer = new MetricTimer();
verify(metricsEmitter, times(1)).emitCount("WorkState:" + associateWorkState.getEmployeeIdentifier(), "Info", associateWorkState.getAssociateWorkStatus().getIndex(),
metricTimer.getSystemStartTimeMillis());
}
Here is the stack:
[junit] Argument locationId must not be null
[junit] com.google.common.base.VerifyException: Argument locationId must not be null
[junit] at com.amazon.ergocommon.util.ValidationHelper.checkNotNull(ValidationHelper.java:39)
[junit] at com.amazon.ergocommon.util.ValidationHelper.checkNotNullOrEmpty(ValidationHelper.java:22)
[junit] at com.amazon.ergocommon.businessobjects.LocationIdentifier.<init>(LocationIdentifier.java:18)
[junit] at com.amazon.ergocommon.businessobjects.WarehouseId.<init>(WarehouseId.java:21)
[junit] at com.amazon.ergocommon.handler.Mbm2TriggerHandler.triggerOnCourseType(Mbm2TriggerHandler.java:163)
[junit] at com.amazon.ergocommon.handler.Mbm2TriggerhandlerTest.handle_emitMetric(Mbm2TriggerhandlerTest.java:231)
Thank you for any help!!

Related

How to write unit test for spring cloud stream function based method?

When I try to test a spring cloud stream function based method, it always happens NullPointerException about InputDestination.
I have two questions:
It's hard for me to know how to write UT from the official doc. official test doc
Besides, how to write integration Test if test file has some dependencies. It seems create a new context and always has NoSuchBeanDefination error.
I have tried as flow, but the context can not find some dependency beans.
#Test
public void sampleTest() {
try (ConfigurableApplicationContext context = new SpringApplicationBuilder(
TestChannelBinderConfiguration.getCompleteConfiguration(
MyTestConfiguration.class))
.run("--spring.cloud.function.definition=uppercase")) {
InputDestination source = context.getBean(InputDestination.class);
OutputDestination target = context.getBean(OutputDestination.class);
source.send(new GenericMessage<byte[]>("hello".getBytes()));
assertThat(target.receive().getPayload()).isEqualTo("HELLO".getBytes());
}
}
So I just want to write UT, but still have NPE.
Here is my code.
#Bean
public Function<Message<List<DemoBean>>, Message<DemoBean>> findFirstBean( ){
return message -> {
List<DemoBean> demoBeans = message.getPayload();
return MessageBuilder.withPayload(demoBeans.get( 0 )).build();
};
}
Here is my test.
#SpringBootTest
#ActiveProfiles(profiles = "local")
#Import({ TestChannelBinderConfiguration.class})
class FunctionDemoTest {
#Autowired
private InputDestination inputDestination;
#Autowired
private OutputDestination outputDestination;
private FunctionDemo functionDemo;
// some dependency need to mock
private DemoService demoService;
#BeforeEach
void setUp() {
demoService = Mockito.mock( DemoService.class );
functionDemo = new FunctionDemo( demoService);
}
#Test
public void findFirstBeanTest() {
DemoBean demoBean = new DemoBean();
demoBean.setName("Howard");
demoBean.setAge( 1 );
DemoBean demoBean1 = new DemoBean();
demoBean1.setName("Frank");
demoBean1.setAge( 2 );
List<DemoBean> demoBeanList = new ArrayList<>();
demoBeanList.add( demoBean );
demoBeanList.add( demoBean1 );
Message<List<DemoBean>> inputMessage = MessageBuilder.withPayload(demoBeanList).build();
inputDestination.send(inputMessage,"findFirstBean-in-0");
Assertions.assertNotNull( outputDestination.receive( 10000, "findFirstBean-out-0") );
}
}
Here is error:
java.lang.NullPointerException: while trying to invoke the method org.springframework.messaging.SubscribableChannel.send(org.springframework.messaging.Message) of a null object returned from org.springframework.cloud.stream.binder.test.InputDestination.getChannelByName(java.lang.String)
at org.springframework.cloud.stream.binder.test.InputDestination.send(InputDestination.java:89)
at com.successfactors.caf.listener.FunctionDemoTest.raePdrResultProcessor(FunctionDemoTest.java:82)
Well, I know the root cause of NPE.
Message<byte[]> receive(long timeout, String bindingName)
It seems should be destinationName instead of bindingName in source code.
Any other answers would be appreciated.

Junit Unable to return mocked Response and return as null

I m new to Mockito and trying to mock the webservice responses, I did tried mocking at some extent few Objects got worked, But the end mocked WebResponse is always returning null.
Service Method i am going to test:getWebResponse Method
public WebResponse getWebResponse(String crmNumber) throws JSONException, ExecutionException, WebException {
Map<String, String> HEADERS_POST = new HashMap<String, String>() {
{
put(WebUtil.HEADER_CONTENT, WebUtil.CONTENT_JSON);
put(WebUtil.HEADER_ACCEPT, WebUtil.CONTENT_JSON);
}
};
JSONObject requestJson = new JSONObject();
requestJson.put("crmNumber", crmNumber);
requestJson.put("application", "ABCD");
requestJson.put("feature", "DDDFL");
// Using internal web service becuase device authentication is done separately.
String url = CommonUtil.getServiceBaseUrl(true) + "/ett";
WebServiceClient client = WebServiceClientRegistry.getClient(ApacheCustom.class);
WebRequest webReq = new GenericWebRequest(WebRequestMethod.POST, url, HEADERS_POST, requestJson.toString());
// Till here i m getting all mocked object (client also Mocked) after this stament the webRes is returning null;
WebResponse webRes = client.doRequest(webReq);
return webRes;
}
And here the test Method:
#Test
public void getWebResponseTest() {
mockStatic(CommonUtil.class);
mockStatic(WebServiceClientRegistry.class);
this.webResponse = new GenericWebResponse(200, "", new HashMap(), "");
try {
Mockito.when(CommonUtil.getServiceBaseUrl(true)).thenReturn("https://stage.com/service");
WebRequest webReq = new GenericWebRequest(WebRequestMethod.POST, "https://stage.com/service", new HashMap(), "");
Mockito.when(WebServiceClientRegistry.getClient(ApacheCustom.class)).thenReturn(client);
Mockito.when(client.doRequest(webReq)).thenReturn(this.webResponse);
WebResponse wesponse = this.ServiceResponse.getWebResponse("Number");
Assert.assertEquals(wesponse.getStatusCode(), 200);
} catch (Exception e) {
Assert.fail();
}
}
But the getWebResonse method from Test class always returning null Response(Even Though it is mocked)
You mock client.doRequest as follows:
Mockito.when(client.doRequest(webReq)).thenReturn(this.webResponse);
but you create a new instance of WebRequest in your service under test.
You call doRequest with a different argument than recorded in your test.
Arguments are compared with equals.
Most likely WebRequest does not override equals, so recorded interaction is ignored and a default response (null) is rerurned.
I guess WebResuest may not be the code you own (you haven’t specified this in your question), so it may be impossible to override it.
Thus, you can use a different argument matcher.
You can use ArgumentMatchers.any() for good start, or implement a custom argument matcher.

mockito NullPointerException

Hi I have the following test and I cannot make it work, its giving NullPointerException:
Method to test :
private ResponseEntity getDefaultCart(HttpEntity<String> request, String zoomQuery) {
LOG.info("Get user's default cart with zoom query" + zoomQuery);
String defaultCartUrl = cortexApiUrl + Constants.CARTS + scope + Constants.DEFAULT + Constants.ZOOM + zoomQuery;
return baseRepository.getCall(defaultCartUrl, request);
}
Junit of this method:
#Test
public void testUpdateCart() {
MockitoAnnotations.initMocks(this);
cortexRepository= new CortexRepositoryImpl("https://abc.juy", "ocean", baseRepositoryImpl);
Mockito.when(baseRepositoryImpl.createRequestHeaders("guestId")).thenReturn(httpHeaders);
JSONObject orderDetails = createCortexCreateOrderObject("cortexCreateOrderResponse.json");
ResponseEntity<JSONObject> entity=new ResponseEntity<JSONObject>(orderDetails,HttpStatus.ACCEPTED);
HttpEntity<String> request = new HttpEntity<String>(httpHeaders);
Mockito.when(baseRepositoryImpl.getCall("http://www.abc.hyh", request)).thenReturn(entity);
cortexRepository.updateCart(updateCartRequest);
}
Method getDefaultCart is calling from updateCart method.The object orderDetails is filling correctly.
NUllPointer is giving on line : baseRepository.getCall(defaultCartUrl, request).
Any suggestion ??
I think that the instance of BaseRepositoryImpl being used when you call baseRepository.getCall(defaultCartUrl, request); is not the same instance being passed to new CortexRepositoryImpl("https://abc.juy", "ocean", baseRepositoryImpl);.
So make sure that you are not creating a new instance of it in CortexRepositoryImpl and are in fact using the object passed into the constructor.
I can't be sure without the source of CortexRepositoryImpl but this seems like the most likely issue.

Mockito, how to verify parameters of ther method in the last time it was called

During executing unit test the method is called 3 times. Each time it's called with different parameters. I want to verify, that on the last time method was called with corresponding paramets.
Please, help me.
My method :
private void doHandle(Updategram updategram)
throws FixtureNotFoundException, DatatypeConfigurationException {
BetSyncObject betSyncObject = transformer.transformer(updategram);
EventTreeCreation event = betSyncObject.eventTree;
if (!event.getEvent().isEmpty()) {
Event event2 = event.getEvent().get(0);
long timestamp =
updategram.getHeader().getTimeStampUtc().toGregorianCalendar().getTimeInMillis();
String sportName = event2.getSportcode();
String id = event2.getExtId();
publisher.publishEvent(PROVIDER_NAME, betSyncObject, sportName, id, timestamp);
} else {
LOGGER.info("Empty event tree : {}", betSyncObject);
}
}
Test:
#Test
public void testCountAndSetResultLine() throws Exception{
EventPublisher eventPublisher = Mockito.mock(EventPublisher.class);
BetgeniusService betgeniusService = new BetgeniusService();
BetSyncObject expectedBetSyncObj = transformer.transformer(updategram);
ExecutorService service = Executors.newFixedThreadPool(3);
handle(betgeniusService, updategramFixture, service);
Thread.sleep(50);
handle(betgeniusService, updategramMarketSet, service);
Thread.sleep(50);
handle(betgeniusService, updategramResult, service);
service.shutdown();
service.awaitTermination(20000, TimeUnit.MILLISECONDS);
betgeniusService.getExecutor().shutdown();
betgeniusService.getExecutor().awaitTermination(20000, TimeUnit.MILLISECONDS);
Mockito.verify(eventPublisher, Mockito.times(3)).publishEvent(Mockito.anyString(), Mockito.any(BetSyncObject.class),
Mockito.anyString(), Mockito.anyString(), Mockito.anyLong());
}
For this moment I am getting exception, because the publishEvent method is not called 3 times with exactly expectedBetSyncObj. It should be called with it only last time.
So, please tell how could I check that the publishEvent method was called with the expectedBetSyncObj object the last time.
I think you can achieve this with an ArgumentCaptor.
Use the ArgumentCaptor to get the arguments for all calls made and then later verify each one of them.
In your case you would verify that on the third call the argument (.get(2)) is the expected object.
So something like
ArgumentCaptor<BetSyncObject> betSyncObjectCaptor = ArgumentCaptor.forClass(BetSyncObject.class);
Mockito.verify(eventPublisher, Mockito.times(3)).publishEvent(Mockito.anyString(), betSyncObjectCaptor.capture(), Mockito.anyString(), Mockito.anyString(), Mockito.anyLong());
List<BetSyncObject> capturedBetSyncObject = betSyncObjectCaptor.getAllValues();
assertEquals(expectedBetSyncObj, capturedBetSyncObject.get(2));

PHPUnit is reporting errors instead of recognizing assertFalse()

I am attempting to test a simple Laravel model which has required "password" and "email" properties. My test reads as follows…
public function testEmailIsRequired() {
$user = new User;
$user->password = 'derp';
// should not save
$this->assertFalse($user->save());
}
Rather than correctly agree that "this doesn't work" and a successful test, I’m getting…
1) UserTest::testEmailIsRequired
Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation:
19 NOT NULL constraint failed: users.email
(SQL: insert into "users" ("password", "updated_at", "created_at")
values (derp, 2014-09-26 15:27:07, 2014-09-26 15:27:07))
[...]
FAILURES!
Tests: 1, Assertions: 0, Errors: 1.
I’m afraid that I’m a total novice here. It seems to me that PHPUnit ought to be suppressing the database driver’s own error reporting and just accepting "false"… help?
Your test is looking for the function to return false. Any other errors generated in your function will still be returned, since you are calling the function.
public function testEmailIsRequired()
{
$user = new User;
$user->password = 'derp';
// should not save
$this->assertFalse($user->save());
}
public function testMockSaveWorks()
{
$Mock = $this->getMock('User', array('save'));
// Set up the expectation for the getResult() method
$Mock->expects($this->any())
->method('save')
->will($this->returnValue(true));
$this->assertTrue($Mock->save());
}
class User()
{
...
public function save()
{
if( is_null($this->email) )
return false;
...
return true;
}
}
You should then use Mocks to remove the actual save() function and its tie in to your database, and have the mock return true to pretend to save the record to show that you have tested the module.