Home > Software design >  Why i can't save anything in my mocked repository
Why i can't save anything in my mocked repository

Time:11-16

I'm learning testing in spring boot, i have this test:

 @ExtendWith(MockitoExtension.class)
 @SpringBootTest
class AppUserServiceTest {

@Mock
private UserRepository repository;
private UserService userService;

@BeforeEach
void setUp() {
    userService = new UserService(repository);
}


@Test
void itShouldLoadUsernameByName() {
    AppUser appUser = new AppUser(
            ApplicationRole.USER,
            "leonardo",
            "rossi",
            "leo__",
            "[email protected]",
            "password"
    );

    repository.save(appUser);

    userService.loadUserByUsername(appUser.getUsername());
    verify(repository).searchByUserName(appUser.getUsername());

}

}

it keep throwing me an exception because it doesn't find any user in the database, in fact even if i save the user the repository.findAll() return 0 element.

This is my User service that i'm trying to test:

@AllArgsConstructor
@Service
public class UserService
    implements UserDetailsService {

private final UserRepository repository;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    return repository.searchByUserName(username)
            .orElseThrow(
                    ()-> new UsernameNotFoundException("The username "   username   " has not been found")
            );
}

This is my H2 databse for testing configuration:

spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

CodePudding user response:

A mock is just a mock. It's never actually doing something. It just can behave like a real thing, but you have to tell the mock how to do it.

So if you mock the UserRepository and try to save something nothing will happen. Because again, a mock never actually does something. The advantage of this is that you don't actually need the whole infrastructure to unit test a tiny method. Additionally the test gets independent of data. What you can do now is return some data if some method is called.

In your case, you don't need a whole database to test the functionality of the UserService. Thus mocking the repository is a good option. Now since it's a mock you have to tell the mock how to behave for your test case:

@Test
void itShouldLoadUsernameByName() {
    AppUser appUser = new AppUser(
            ApplicationRole.USER,
            "leonardo",
            "rossi",
            "leo__",
            "[email protected]",
            "password"
    );

    when(standortRepository.searchByUserName(any())).thenReturn(appUser);

    userService.loadUserByUsername(appUser.getUsername());

    //More expectations ...

    verify(repository).searchByUserName(appUser.getUsername());    
}

Now what I have done is to tell the mock it should return the appUser, when the Method loadByUsername is called.

P.s. these are the static imports I used:

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
  • Related