Każdy moduł w mojej aplikacji ma publiczną fasade, a reszta jest package scoped, do tego całe DI jest realizowane wewnątrz takich klas:
@Configuration
class EmailConfiguration {
@Bean
EmailFacade emailFacade(EmailSender emailSender) {
return new EmailFacade(emailSender);
}
}
@Configuration
class UserConfiguration {
@Bean
UserFacade userFacade(UserRepository repository, EmailFacade emailFacade) {
return new UserFacade(repository, emailFacade);
}
}
Dopóki mój moduł Usera nie miał zależności do modułu Email, mogłem dzięki temu pisać testy bez odpalania Springa. Package dla domeny i testów Usera jest taki sam, więc mam dostęp do package scope obiektów, co pozwalało na coś takiego
private UserFacade userFacade = new UserConfiguration().userFacade(new InMemoryUserRepository());
Problem pojawił się z dojściem dodatkowej zależności, czyli wspomniany moduł Email.
@RunWith(MockitoJUnitRunner.class)
public class RegisterUserTest {
@Mock
private EmailFacade emailFacade;
@InjectMocks
private UserFacade userFacade = new UserConfiguration().userFacade(new InMemoryUserRepository(), emailFacade);
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void shouldRegisterUser() {
Mockito.when(emailFacade.sendUserVerificationEmail(Mockito.any())).thenReturn(Either.right(new SuccessMessage("")));
assertTrue(userFacade.registerNewUser(RegisterUserDto.builder()
.username(VALID_USERNAME)
.email(VALID_EMAIL)
.password(VALID_PASSWORD).build()).isRight());
}
}
Niestety takie coś rzuca nullpointera przy pierwszym odwołaniu się do emailFacade wewnątrz metody registerNewUser(), no i faktycznie - ta fasada jest nullem. Nie bardzo jednak mogę znaleźć sposobu na to by powyższy test zadziałał tak jak oczekuje.
Próbowałem również zrobić fake'ową implementację EmailSender, czyli zależności EmailFacade.
@Mock
private EmailFacade emailFacade = new EmailFacade(new FakeEmailSender());
Niestety tu pojawia się problem - nie dostaję co prawda nullpointera, ale mocki nie działają na takim obiekcie.
Pomoże ktoś z tego wybrnąć?