Env:
2 datasources - one PostgreSQL and MongoDB
JDK 17
Spring Boot 3.1.1
JUnit 4
当 updateScheduler 服务为 @DataJpaTest 调用时,eventRepository 不返回模拟。
使用@SpringBootTest时,以下一切都工作正常。
我缺少什么?
@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());
}
总而言之,这是一些人为错误。让我解释一下,以便其他面临同样问题的人可以退后一步,看看是否相同。
我的测试需要 ID。
var r0 = resultadoRepository.findById(1L).get();
使用
@AutoConfigureTestDatabase
每次测试都会增加底座上的 ID。
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
要解决这个问题,我只需要设置
DirtiesContext
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
在调试服务时,我注意到没有返回模拟 - 所以我不再认为存在问题。但是,我真的不知道,为什么mockito运行两次。如果我继续调试,我会再次使用正确的模拟,并且测试成功。
与
@SpringBootTest
工作方式相同,但需要 @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;
如果有人告诉我,我可以接受第二个答案:
DirtiesContext
谢谢