First, I'll explain how the mos work and how to use them in tests.When in a test that starts with help SpringRunnersome field marked by annotations @MockBeanthe corresponding bin in the context of the Spring is replaced by mok. This means that in the context of testing, there is no real implementation AccountRepository (i.e. the one that keeps in the database or which is the configured repository). This mock will be introduced as dependence on bean used AccountRepository (in our case) StudentService)What's a bow? This is an object that operates the interface (for) accountRepository That's it. AccountRepository() and, by every method of which nothing and default returns the default value.Let's look at example. AccountRepository♪If the mok doesn't configuration, call. findAccountByEmail It will do nothing (in the sense not to keep the subject in the OBD system) and return the default value to Account, i.e. null (for all objective types it will be) nulland for type awards int ♪ 0♪ boolean - false etc. https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html )That is why the challenge is:Account account = accountRepository.findAccountByEmail(dto.getEmail());
He's back in the test. null♪Teper's short on why we need moki.Implementation of the class StudentService Depends on other classes, in particular AccountRepository♪ For testing StudentService I want to.He's isolated from addictions, that's to test the logic of the class itself, not the logic. AccountRepository and Otheremulate situations that cannot always be predictable in the real system (e.g. network failure)That's what we use, i.e., fakes. The point is, before we do the test code, we'll configuration them (or build them) to do what we need for this test scenario. For example, we can point out that when calling findAccountByEmail I have to go back. nullbecause account- and there's no such mail.Further, after the code is tested, we can verify that the moca method was caused by the parameters that we expect in this test scenario (e.g. that the right role was established).We're looking at an example from the question. There's a test here to verify, among other things, that if there's no such thing. account- and with a given postal address, it will be created and will have a role to play.The test of this scenario is about to look like:@Test
public void addStudentCreatesNewAccount() {
String someEmail = 'some@email.com'
// тут я предполагаю, что isAccountExists пользуется findAccountByEmail
// чтобы определить существует ли account с заданой почтой
when(accountRepository.findAccountByEmail(someEmail)).thenReturn(null);
CreateStudentDto dto = new CreateStudentDto();
dto.setEmail(someEmail);
studentService.addStudent(dto);
// ArgumentCaptor позволяет захватить и запомнить значение, которое
// было передано, как аргумент в метод мока, чтобы его проверить
ArgumentCaptor<Account> accountCaptor = ArgumentCaptor.forClass(Account.class);
verify(accountRepository).save(accountCaptor.capture());
Account savedAccount = accountCaptor.getValue();
assertThat(savedAccount.getRole(), equalTo((byte)1));
assertThat(savedAccount.getEmail(), equalTo(someEmail));
}
Just to understand the principle. In practice, for example, I ArgumentCaptor I don't use it, but I do. MockitoHamcrest.argThat + matchers. Furthermore, the mok configuration is hidden in higher-level methods, such as:void givenAccountForEmailDoesNotExist(String email) {
when(accountRepository.findAccountByEmail(someEmail)).thenReturn(null);
}
etc. The main principle is to hide the details of implementation and to make the test more readable and less dependent on the details of implementation.