Env:
2 datasources - one PostgreSQL and MongoDB
JDK 17
Spring Boot 3.1.1
JUnit 4
eventRepository is not returning mock when called by updateScheduler Service for @DataJpaTest.
Everything bellow works fine when using @SpringBootTest.
What I am missing?
@MockBean EventRepository eventRepository;
when(this.eventRepository.findByIdentifierFlapIn(any())).thenReturn(mock);
@Repository
public interface EventRepository extends MongoRepository<Flap, String> {
List<Flap> findByIdentifierFlapIn(List<String> identifierFlap);
//Everything commented is what I am experiencing the problem. Not commented just works fine
@RunWith(SpringRunner.class)
//@DataJpaTest
//@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
//@ComponentScan(basePackages = {"com.X.resultado", "com.X.updates"})
//@Import({
// Configuracao.class,
// EventRepository.class
//})
@SpringBootTest
@TestPropertySource("classpath:application-test.properties")
public class TestUpdater {
@Autowired
ResultadoRepository resultadoRepository;
@MockBean
EventRepository eventRepository;
@InjectMocks @Autowired
UpdateScheduler updateScheduler;
(...)
@Before
public void setUp() {
closeable = MockitoAnnotations.openMocks(this);
resultadoBaronezaList = List.of(
new ResultBar(),
new ResultBar(),
new ResultBar()
);
ResultBarList.get(0).setId(1L);
ResultBarList.get(0).setIdentifierFlap("identifier1");
(...)
}
@Service
public class UpdateScheduler {
private final Logger logger = getLogger(this.getClass());
private final ResultadoRepository resultadoRepository;
private final EventRepository eventRepository;
@Autowired
public UpdateScheduler(ResultadoRepository resultadoRepository, EventRepository eventRepository) {
this.resultadoRepository = resultadoRepository;
this.eventRepository = eventRepository;
}
@Scheduled(fixedRateString = "${bar.timeUpdate}")
public void verificaAtualizacoes() {
List<ResultadoBar> ativos = resultadoRepository.findAllByType("1");
List<String> identifierFlapList = ativos.stream().map(ResultadoBar::getIdentifierFlap).toList();
//**HERE the mock is not working**
List<Flap> flapsModificados = eventRepository.findByIdentifierFlapIn(identifierFlapList);
List<ResultadoBar> resultadoBarList = new ArrayList<>();
(...)
@Test
public void validaClearForcado(){
resultadoRepository.saveAll(resultadoBarList);
List<Flap> mock = new ArrayList<>(flapList);
mock.get(0).setLastSeenFlap("Feb 27, 2024 3:00:00 PM");
when(this.eventRepository.findByIdentifierFlapIn(any())).thenReturn(mock);
updateScheduler.verificaAtualizacoes();
var r0 = resultadoRepository.findById(1L).get();
assertEquals(LocalDateTime.of(2024,2,27,15,0,0), r0.getDataUltimoFlap());
assertTrue(r0.isClearForcado());
}
In summary was a bit of human error. Let me explain so others facing the same issue can take a step back and see if it is the same.
My tests needs the ID.
var r0 = resultadoRepository.findById(1L).get();
With @AutoConfigureTestDatabase
each test will increment the ID on the base.
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
To fix that I just need to set DirtiesContext
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
When debugging the service I was noticing that was not returning the mock - so I was stopping thinking there were a problem. But, I really don't know, why mockito runs twice. If I resume the debug, I got again in the line with the correct mock and the test is successful.
Works the same as the @SpringBootTest
but it needs @DirtiesContext
@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@ComponentScan(basePackages = {"com.X.resultado", "com.X.updates"})
@Import({
Configuracao.class,
EventRepository.class
})
//@SpringBootTest
@TestPropertySource("classpath:application-test.properties")
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
public class TestUpdater {
@Autowired
ResultadoRepository resultadoRepository;
@MockBean
EventRepository eventRepository;
@InjectMocks @Autowired
UpdateScheduler updateScheduler;
I can accept a second answer if someone tell me:
DirtiesContext
Thanks