@MockBean does not get mocked when using @DataJpaTest

48 Views Asked by At
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());
    }
1

There are 1 best solutions below

1
Goldman7911 On BEST ANSWER

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.

enter image description here

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:

  • Why "mockito/whataver" pass twice in the same code
  • Why @SpringBootTest doesn't need DirtiesContext

Thanks