My service test fails when I have an if statement in the class under test SpringBoot

Viewed 46

I am writing tests from my springboot application. The class has a method getUserById which returns Optional<User>. This methos has an if statement that will check whether an row was returned from repository before sending a response. Problem: With the if statement in place, my test always throws the error in the if statement. when I remove the if statement, the test passes. What am I missing?

This is my UserServiceImpl (Class under test)

@Service
@RequiredArgsConstructor
@Transactional
@Slf4j
public class UserServiceImpl implements UserService, UserDetailsService {
    @Autowired
    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;

    @Override
    public List<User> getUsers() {
        log.info("Fetching users");
        return userRepository.findAll();
    }

    @Override
    public Optional<User> getUserById(Long id) {
        log.info("Fetching user id: {}", id);
        Optional<User> user = userRepository.findById(id);
        if (!user.isPresent()) {
            throw new ResourceNotFoundException(MessageUtil.ERROR_USER_NOTFOUND);
        }
        return user;
    }
}

This is my UserServiceImplTest (test class)

@RunWith(SpringRunner.class)
@SpringBootTest
class UserServiceImplTest {

    @MockBean
    private UserRepository userRepositoryTest;

    @InjectMocks
    private UserServiceImpl userServiceTest;

    @Mock
    private PasswordEncoder passwordEncoder;

    private List<User> userSet;
    private User user1;
    private User user2;

    @BeforeEach
    void setUp() {
        userServiceTest = new UserServiceImpl(userRepositoryTest, passwordEncoder);

        Set<ApplicationUserRole> roles = new HashSet<>();
        roles.add(ApplicationUserRole.TEST_USER);
        userSet = new ArrayList<>();

        user1 = User.builder().nickname("test-nickname")
                .id(1L)
                .username("254701234567")
                .roles(roles)
                .password("password")
                .build();

        user2 = User.builder().nickname("test2-nickname2")
                .id(2L)
                .username("254701234589")
                .roles(roles)
                .password("password")
                .build();

        userSet.add(user1);
        userSet.add(user2);

        userSet.stream().forEach(user -> {
            userServiceTest.saveUser(user);
        });
    }

    @AfterEach
    void tearDown() {
    }

    @Test
    void testGetUsers() {
        when(userServiceTest.getUsers()).thenReturn(userSet);
        assertEquals(2, userServiceTest.getUsers().size());
        verify(userRepositoryTest).findAll();
    }

    @Test
    void testGetUserById() {
        when(userServiceTest.getUserById(user1.getId())).thenReturn(Optional.ofNullable(user1));
        assertEquals(1, user1.getId());
        verify(userRepositoryTest).findById(user1.getId());
    }

    @Test
    void testSaveUser() {
        when(userServiceTest.saveUser(user1)).thenReturn(user1);
        assertEquals(1L, user1.getId());
        verify(userRepositoryTest).save(user1);
    }

    @Test
    void updateUser() {
        user1.setNickname("nickname-update");
        when(userServiceTest.saveUser(user1)).thenReturn(user1);
        assertEquals("nickname-update", user1.getNickname());
        verify(userRepositoryTest).save(user1);
    }

}

NOTE: Other tests work just fine

1 Answers

You are trying to mock the service method call but the service is autowired — that doesn’t work. You can mock instead the repository method call since the repository is annotated as MockBean, that should work.

Related