I am using mockito to mock a JpaRepository class that returns a list of Object[]. The mocking is as follow:
@MockBean
private UtilisateurSuiviRepository utilisateurSuiviRepository;
So I'm using this mock object o test diffrent scenarios and return different results.
In the first test method I have this:
when(utilisateurSuiviRepository
.findUtilisateursInactifsPourPremiereRelance(10))
.thenReturn(new ArrayList<Object[]>(){{
add(new Object[]{8L, Instant.now()});
}});
In the second test method I have the same thing but with different parameter and return result:
when(utilisateurSuiviRepository
.findUtilisateursInactifsPourPremiereRelance(16))
.thenReturn(new ArrayList<Object[]>(){{
add(new Object[]{5L,null});
}});
The problem is that depending on the execution order of the methods, my second method remember also the return result of the first mock, so it returns two lists :
new Object[]{8L, Instant.now() // <-- first list of array object
new Object[]{5L,null} //<-- second list of array object
Expecting result is:
new Object[]{5L,null} //<-- what should I get in the second method
I'am aware that mockito keeps the same state for all mocks, so I did this to init the mocks before each test method:
@Before
public void setUp(){
MockitoAnnotations.initMocks(this);
}
But it does not change anything and I keep getting the same issue.
Note that I'm using SpringRunner to run my test class in a context of spring batch:
@RunWith(SpringRunner.class)
@MyCustomBatchUnitTest
@TestPropertySource(properties = {"spring.batch.job.names=myJob"})
The definition of MyCustomBatchUnitTest is as follow:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@SpringBootTest(classes = { CommonsConfiguration.class })
@AutoConfigureMockMvc
@ActiveProfiles({CommonsConfiguration.PROFILE_BATCH, CommonsConfiguration.PROFILE_TEST, CommonsConfiguration.PROFILE_BATCHTEST})
public @interface MyCustomBatchUnitTest{
}
I tried also to init the mock manually inside each method as follow:
utilisateurSuiviRepository = mock(UtilisateurSuiviRepository.class);
when(utilisateurSuiviRepository
.findUtilisateursInactifsPourPremiereRelance(16))
.thenReturn(new ArrayList<Object[]>(){{
add(new Object[]{8L, Instant.now()});}});
But in that case the mock method that is just after is not being processed.
Bellow a github link that produce the same problem: https://github.com/MrPenguina/mockito_issue/blob/main/JobTest.java
As explained by the guys in the comments, I had to use:
Because
MockitoAnnotations.initMocksmethod is used within@Mockof Mockito framework and not for@MockBeanof spring framework.Also note that in the context of Spring Batch, I had a final
Listthat I initialize in the declaration, the list is used to hold the result of myJpaRepositoryby calling the methodaddAllinside thebeforeStepmethod, which was causing the issue in my case and kept giving me a cumulative result:I had to move the initialization of this list inside the
beforeStep()of the reader so like that the list will be initialized each time whenever a test method is called.In conclusion, I had to correct the mistake above and to use
Mockito.resetmethod inside the@Beforemethod.UPDATE
Other alternative to keep the list intitialization in the declaration instead is to use the annotation
@DirtiesContextwithing the test class: