Piszę testy jednostkowe dla implementacji usługi, która używa repozytorium JPA - MessageRepository, która zwraca „Poszukiwany, ale nie wywołany: w rzeczywistości nie było żadnych interakcji z tym modelem”, gdy próbuję sprawdzić, czy jest wywoływany. Wyodrębniłem fragmenty kodu, aby uprościć wyjaśnienie problemu.
Wdrożenie usługi:
public class MessageServiceImpl {
private final MessageRepository messageRepository;
public MessageServiceImpl(MessageRepository messageRepository) {
this.messageRepository = messageRepository;
}
public Message create(){
Message result;
//some operations...
Message message = new Message();
message.setId(2L);
message.setName("123231231");
...
result = save(message);
return result;
}
public Message save(Message message){
Message result = messageRepository.save(message); // returns a null when I debug while Testing
return result;
}
}
Klasa testów jednostkowych
@RunWith(SpringRunner.class)
public class MessageServiceImplUnitTest {
@Mock
MessageRepository messageRepository;
@Mock
OtherService otherService; // not a jpa repo but uses one in its implementation and works just as expected
@InjectMocks
MessageServiceImpl messageService;
Message message;
@Before
public void setup() {
initMocks(this);
message = new Message();
message.setId(1L);
message.setMessageDirection(MessageDirection.OUT);
}
// Unit Test for create method of MessageServiceImpl which should return a non-null Message Obj
@Test
public void createShouldReturnNotNullMessageObj(){
// mocking save method to return the same Obj that was passed
when(messageRepository.save(any(Message.class))).then(AdditionalAnswers.returnsFirstArg());
Message result = messageService.create();
// This fails and displays "Wanted but not invoked: Actually, there were
// zero interactions with this mock"
verify(messageRepository).save(any(Message.class));
Assert.assertNotNull(result);
}
Nie mogę zrozumieć, dlaczego inne usługi pozorowane działają zgodnie z oczekiwaniami, ale repozytorium nie jest wywoływane. W rezultacie obiekt Message Obj jest zwracany jako null z save (Message message) obj.
2 odpowiedzi
Usuń @SpringBootTest(classes = Abc.class)
: to test jednostkowy, a nie test integracji.
Usuń @Autowired
: używasz iniekcji konstruktora.
Usuń messageService = new MessageServiceImpl(messageRepository);
: adnotacje Mockito robią to za Ciebie, a ponieważ masz initMocks()
po tej instrukcji, messageRepository
i tak jest nadal pusty.
Usuń RunWith(MockitoJUnitRunner.class)
, ponieważ dzwonisz pod numer initMocks()
wyraźnie w swoim kodzie.
Używasz @InjectMocks
na swojej zmiennej messageService
. I zainicjuj go w samym konstruktorze.
Zrób jedno z nich, a nie oba, przypuszczam, że na tym polega twój problem. @InjectMock
inicjalizuje twój obiekt i wstrzykuje makiety za ciebie. Jeśli to zrobisz i ręcznie zainicjujesz obiekt, wyniki mogą być nieprzewidywalne.
Twoje okablowanie jest również wyłączone, używasz inicjalizacji konstruktora, ale masz adnotację @Autowired
na polu, przenieś ją do konstruktora.
Masz również adnotację SpringBootTest
na szczycie swojej klasy, która nie jest konieczna do testu jednostkowego.
Podobne pytania
Nowe pytania
java
Java to język programowania wysokiego poziomu. Użyj tego tagu, jeśli masz problemy z używaniem lub zrozumieniem samego języka. Ten tag jest rzadko używany samodzielnie i jest najczęściej używany w połączeniu z [spring], [spring-boot], [jakarta-ee], [android], [javafx], [hadoop], [gradle] i [maven].