I know there are tons of similar questions in SO but yet I couldn't find any solution. I have Service class like this. Inside which there is repository method called which returns void. I have created a mock object of that repo class. And injected in the autowired service class but I am getting "Wanted but not invoked..Actually, there were zero interactions with this mock." I have verfied that the repository does getting called.
` @Service
public class DecileConfigService
{
@Autowired
private ItemAdditionalInfoRepository itemAdditionalInfoRepository;
@Transactional
public Boolean triggerBatchJob(ItemAdditionalInfo existingIAI, ItemAdditionalInfo latestIAI, DecileConfig existingDC, DecileConfig latestDC, String decileNbr, String decileType,String tenantId, String isBulkUpload)
{
if(!existingIAI.equals(latestIAI))
{
System.out.println("Callled ::::::");
itemAdditionalInfoRepository.updateAllocationStatusByItemAndTenantId(ItemSetupAllocationStatus.PROGRESS.getValue(),Integer.valueOf(decileNbr),lastUpdatedBy,lastUpdatedOn,tenantId);
}
}
}`
`
Test class :
@Mock
ItemAdditionalInfoRepository itemAdditionalInfoRepository;
@Autowired
@InjectMocks
private DecileConfigService decileConfigService;`
@Test
public void testRepo() throws Exception
{
ItemAdditionalInfo oldIad = DatabricksUtil.createItem();
oldIad.setVendorNbrFull(12);
ItemAdditionalInfo newIad = DatabricksUtil.createItem();
newIad.setVendorNbrFull(13);
DecileConfig dc = DatabricksUtil.createDecile();
decileConfigService.triggerBatchJob(oldIad, newIad, dc, dc, "200", "item", ConstantsUtil.tenantIdValueUS,"false");
//doNothing().when(itemAdditionalInfoRepository).updateAllocationStatusByDeptAndTenantId(ItemSetupAllocationStatus.PROGRESS.getValue(), Integer.valueOf("200"),newIad.getLastUpdatedBy(),newIad.getLastUpdatedOn(), newIad.getTenantId());
verify(itemAdditionalInfoRepository,times(1)).updateAllocationStatusByDeptAndTenantId(ItemSetupAllocationStatus.PROGRESS.getValue(), Integer.valueOf("200"),newIad.getLastUpdatedBy(),newIad.getLastUpdatedOn(), newIad.getTenantId());
}`
LOG:
Callled :::::: Hibernate: update item_additional_info set allocation_status=?, last_updated_by=?, last_updated_on=? where item_nbr=? and tenant_id=? 27/May/2023 15:47:34:909 [main] INFO com.walmart.sams.services.allocation.configuration.service.TriggerJobService:59 - info env dev-test url test jobId testid params {decileLevelType=item, autoUpdate=false, decileLevelNumber=200, triggerBy=null, source=Single Edit Trigger, isBulkUpload=false} 27/May/2023 15:47:34:910 [main] INFO com.walmart.sams.services.allocation.configuration.service.TriggerJobService:61 - info env dev-test url test jobName testid params {decileLevelType=item, autoUpdate=false, decileLevelNumber=200, triggerBy=null, source=Single Edit Trigger, isBulkUpload=false} 27/May/2023 15:47:34:989 [main] ERROR com.walmart.sams.services.allocation.configuration.service.TriggerJobService:34 - Error {} java.lang.IllegalArgumentException: URI is not absolute at java.net.URL.fromURI(URL.java:692) ~[?:?] at java.net.URI.toURL(URI.java:1116) ~[?:?] at org.springframework.http.client.SimpleClientHttpRequestFactory.createRequest(SimpleClientHttpRequestFactory.java:145) ~[spring-web-5.3.27.jar:5.3.27] at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:98) ~[spring-web-5.3.27.jar:5.3.27] at com.walmart.platform.txn.springboot.interceptor.SpringBootClientTxnMarkingInterceptor.intercept(SpringBootClientTxnMarkingInterceptor.java:82) ~[strati-af-txn-marking-springboot-client-4.5.9.jar:?] at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:93) ~[spring-web-5.3.27.jar:5.3.27] at org.springframework.http.client.InterceptingClientHttpRequest.executeInternal(InterceptingClientHttpRequest.java:77) ~[spring-web-5.3.27.jar:5.3.27] at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) ~[spring-web-5.3.27.jar:5.3.27] at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:66) ~[spring-web-5.3.27.jar:5.3.27] at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:782) ~[spring-web-5.3.27.jar:5.3.27] at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:717) ~[spring-web-5.3.27.jar:5.3.27] at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:474) ~[spring-web-5.3.27.jar:5.3.27] at com.walmart.sams.services.allocation.configuration.service.TriggerJobService.runDatabricksJob(TriggerJobService.java:75) ~[classes/:?] at com.walmart.sams.services.allocation.configuration.service.TriggerJobService.runBatchJob(TriggerJobService.java:31) [classes/:?] at com.walmart.sams.services.allocation.configuration.service.DecileConfigService.triggerBatchJob(DecileConfigService.java:496) [classes/:?] at com.walmart.sams.services.allocation.configuration.service.DecileConfigService$$FastClassBySpringCGLIB$$1122e4d.invoke(<generated>) [classes/:?] at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) [spring-core-5.3.27.jar:5.3.27] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) [spring-aop-5.3.27.jar:5.3.27] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) [spring-aop-5.3.27.jar:5.3.27] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) [spring-aop-5.3.27.jar:5.3.27] at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) [spring-tx-5.3.27.jar:5.3.27] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) [spring-tx-5.3.27.jar:5.3.27] at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) [spring-tx-5.3.27.jar:5.3.27] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) [spring-aop-5.3.27.jar:5.3.27] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) [spring-aop-5.3.27.jar:5.3.27] at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) [spring-aop-5.3.27.jar:5.3.27] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) [spring-aop-5.3.27.jar:5.3.27] at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) [spring-aop-5.3.27.jar:5.3.27] at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) [spring-aop-5.3.27.jar:5.3.27] at com.walmart.sams.services.allocation.configuration.service.DecileConfigService$$EnhancerBySpringCGLIB$$8cc50e9e.triggerBatchJob(<generated>) [classes/:?] at com.walmart.sams.services.allocation.configuration.test.DatabricksJobServiceTest.testRepo(DatabricksJobServiceTest.java:163) [test-classes/:?] at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?] at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?] at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?] at java.lang.reflect.Method.invoke(Method.java:566) ~[?:?] at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59) [junit-4.13.2.jar:4.13.2] at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.13.2.jar:4.13.2] at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56) [junit-4.13.2.jar:4.13.2] at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) [junit-4.13.2.jar:4.13.2] at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74) [spring-test-5.3.27.jar:5.3.27] at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84) [spring-test-5.3.27.jar:5.3.27] at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) [spring-test-5.3.27.jar:5.3.27] at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86) [spring-test-5.3.27.jar:5.3.27] at org.mockito.internal.junit.VerificationCollectorImpl$1.evaluate(VerificationCollectorImpl.java:37) [mockito-core-4.5.1.jar:?] at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84) [spring-test-5.3.27.jar:5.3.27] at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366) [junit-4.13.2.jar:4.13.2] at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251) [spring-test-5.3.27.jar:5.3.27] at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97) [spring-test-5.3.27.jar:5.3.27] at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331) [junit-4.13.2.jar:4.13.2] at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79) [junit-4.13.2.jar:4.13.2] at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329) [junit-4.13.2.jar:4.13.2] at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66) [junit-4.13.2.jar:4.13.2] at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293) [junit-4.13.2.jar:4.13.2] at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) [spring-test-5.3.27.jar:5.3.27] at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) [spring-test-5.3.27.jar:5.3.27] at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) [junit-4.13.2.jar:4.13.2] at org.junit.runners.ParentRunner.run(ParentRunner.java:413) [junit-4.13.2.jar:4.13.2] at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190) [spring-test-5.3.27.jar:5.3.27] at org.junit.runner.JUnitCore.run(JUnitCore.java:137) [junit-4.13.2.jar:4.13.2] at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69) [junit-rt.jar:?] at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33) [junit-rt.jar:?] at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235) [junit-rt.jar:?] at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54) [junit-rt.jar:?]
org.mockito.exceptions.base.MockitoAssertionError: There were multiple verification failures: Wanted but not invoked: itemAdditionalInfoRepository.updateAllocationStatusByDeptAndTenantId(
"In progress", 200, null, null,
"sams_us" ); at com.walmart.sams.services.allocation.configuration.test.DatabricksJobServiceTest.testRepo(DatabricksJobServiceTest.java:165) Actually, there were zero interactions with this mock.
You must make a choice : do you want to implement an unit test or an integration test ?
When you use @SpringBootTest annotation, all the Spring beans in you app are instantiated and a Spring ApplicaticationContext is created. You're creating an integration test.
If you need to manipulate some of your Spring beans in your test, you use @Autowire to get your beans injected:
@SpringBootTest
class DecileConfigServiceTest {
@Autowired
ItemAdditionalInfoRepository itemAdditionalInfoRepository;
@Autowired
private DecileConfigService decileConfigService;`
@Test
public void testRepo() throws Exception
{
ItemAdditionalInfo oldIad = DatabricksUtil.createItem();
oldIad.setVendorNbrFull(12);
ItemAdditionalInfo newIad = DatabricksUtil.createItem();
newIad.setVendorNbrFull(13);
DecileConfig dc = DatabricksUtil.createDecile();
decileConfigService.triggerBatchJob(oldIad, newIad, dc, dc, "200", "item", ConstantsUtil.tenantIdValueUS,"false");
//doNothing().when(itemAdditionalInfoRepository).updateAllocationStatusByDeptAndTenantId(ItemSetupAllocationStatus.PROGRESS.getValue(), Integer.valueOf("200"),newIad.getLastUpdatedBy(),newIad.getLastUpdatedOn(), newIad.getTenantId());
verify(itemAdditionalInfoRepository,times(1)).updateAllocationStatusByDeptAndTenantId(ItemSetupAllocationStatus.PROGRESS.getValue(), Integer.valueOf("200"),newIad.getLastUpdatedBy(),newIad.getLastUpdatedOn(), newIad.getTenantId());
}
}
If you need to mock some of your Spring beans in your integration test, create a configuration class for your test, replace the bean you want to mock in it :
@Profile("decile-test")
@Configuration
public class TestConfiguration {
@Bean
@Primary
public ItemAdditionalInfoRepository mockItemAdditionalInfoRepository() {
return mock(ItemAdditionalInfoRepository.class);
}
}
And add ActiveProfiles annotation on your test class: @ActiveProfiles(value={"decile-test"})
Now, your "normal" Spring bean of type "ItemAdditionalInfoRepository" is replaced by a Mock in your application context and can be "autowired".
If you want to test only your "DecileConfigService" class, and not all your SpringBoot app, with all your Spring beans in the aplication context, don't set "@SpringBootTest" on your test class, and use Mockito to inject the mocked objects.
@RunWith(MockitoJUnitRunner.class) // Junit 4
// @ExtendWith(MockitoExtension.class) - for JUnit 5
class DecileConfigServiceTest {
@Mock
ItemAdditionalInfoRepository itemAdditionalInfoRepository;
@InjectMocks
private DecileConfigService decileConfigService;`
@Test
public void testRepo() throws Exception
{
ItemAdditionalInfo oldIad = DatabricksUtil.createItem();
oldIad.setVendorNbrFull(12);
ItemAdditionalInfo newIad = DatabricksUtil.createItem();
newIad.setVendorNbrFull(13);
DecileConfig dc = DatabricksUtil.createDecile();
decileConfigService.triggerBatchJob(oldIad, newIad, dc, dc, "200", "item", ConstantsUtil.tenantIdValueUS,"false");
//doNothing().when(itemAdditionalInfoRepository).updateAllocationStatusByDeptAndTenantId(ItemSetupAllocationStatus.PROGRESS.getValue(), Integer.valueOf("200"),newIad.getLastUpdatedBy(),newIad.getLastUpdatedOn(), newIad.getTenantId());
verify(itemAdditionalInfoRepository,times(1)).updateAllocationStatusByDeptAndTenantId(ItemSetupAllocationStatus.PROGRESS.getValue(), Integer.valueOf("200"),newIad.getLastUpdatedBy(),newIad.getLastUpdatedOn(), newIad.getTenantId());
}
}
Considering the content of your test class, I think you're doing unit test. So, don't use @SpringBootTest annotation.