Home > Software design >  What is the service or repository to test?
What is the service or repository to test?

Time:01-17

I have a custom query in the repository. And the service that calls this method from the repository.

I want to write a unit test. What should I test for a repository or a service?

Or should I do 2 absolutely identical tests?

CodePudding user response:

You should unit test everything. Test happy-paths sad-paths. The more you test the better your results will be. For repo tests it should be enough to test 1 happy and 1 sad (either you receive the data or you don't) Service tests require more time, say you have a few if-conditions then you would want to test those specific cases as well.

As an example:

@DataJpaTest
class RoleRepoTest {
    @Autowired
    private RoleRepo roleRepo;

    @PersistenceContext
    private EntityManager entityManager;

    @Test
    void itShouldfindRoleByName() {
        // given
        Role role = new Role(null, "administrator");
        roleRepo.save(role);
        flushAndClear();
        // when
        Role roleExpected = roleRepo.findByName("administrator");
        // then
        assertThat(roleExpected.getName()).isEqualTo(role.getName());
    }

    @Test
    void itShouldNotfindRoleByName() {
        // when
        Role expectedRole = roleRepo.findByName("name");
        assertThat(expectedRole).isNull();
    }

    private void flushAndClear() {
        entityManager.flush();
        entityManager.clear();
    }
}

Make sure to always flush & clear. This will avoid your tests from failing when running all at once. It ensures that each test is run in a clean and isolated environment. Without flushing and clearing the database, tests may be affected by data that was created or modified during previous tests.

For Service tests I've got the following example:

@Test
        void deleteUser_givenUser_whenTryingToDeleteSameUser_thenUserDeleted() {
            // given
            given(securityContext.getAuthentication().getPrincipal()).willReturn(userDetails);
            given(userDetails.getUsername()).willReturn(user.getUsername());
            given(userRepo.findByUsername(user.getUsername())).willReturn(user);
            userIsStudent();
            String username = user.getUsername();
            // when
            authService.deleteUser(new DeleteAccountDto(username));
            // then
            verify(userRepo).deactivateUser(username);
        }

        @Test
        void deleteUser_givenLoggedInUserNotAdmin_whenTryingToDeleteUserWithOtherUsername_ThrowError() {
            // given
            String username = studentUser.getUsername();
            // when   then
            assertThatThrownBy(() -> authService.deleteUser(new DeleteAccountDto(username)))
                    .isInstanceOf(AccountException.class)
                    .hasMessage("De gebruikersnaam is niet gevonden.");

            verify(userRepo, never()).deactivateUser(username);
        }

        @Test
        void deleteUser_givenLoggedInUserIsAdmin_whenTryingToDeleteExistingUser_ThenUserIsDeleted() {
            given(securityContext.getAuthentication().getPrincipal()).willReturn(userDetails);
            given(userDetails.getUsername()).willReturn(user.getUsername());
            userIsAdmin();
            // given
            given(userRepo.findByUsername(studentUser.getUsername())).willReturn(studentUser);
            String username = studentUser.getUsername();
            // when
            authService.deleteUser(new DeleteAccountDto(username));
            // then
            verify(userRepo).deactivateUser(username);
        }

        @Test
        void deleteUser_givenLoggedInUserIsAdmin_WhenTryingToDeleteLoggedInUser_ThenThrowError() {
            given(securityContext.getAuthentication().getPrincipal()).willReturn(userDetails);
            given(userDetails.getUsername()).willReturn(user.getUsername());
            userIsAdmin();
            // when   then
            given(userRepo.findByUsername(adminUser.getUsername())).willReturn(adminUser);
            assertThatThrownBy(() -> authService.deleteUser(new DeleteAccountDto(adminUser.getUsername())))
                    .isInstanceOf(AccountException.class)
                    .hasMessage("Administrators can't be deleted");

        }

        @Test
        void deleteUser_GivenLoggedInUserIsAdmin_WhenTryingToDeleteOtherAdmin_ThenThrowError() {
            userIsAdmin();
            given(securityContext.getAuthentication().getPrincipal()).willReturn(userDetails);
            given(userDetails.getUsername()).willReturn(user.getUsername());
            given(userRepo.findByUsername(otherAdminUser.getUsername())).willReturn(otherAdminUser);
            // when   then
            assertThatThrownBy(() -> authService.deleteUser(new DeleteAccountDto(otherAdminUser.getUsername())))
                    .isInstanceOf(AccountException.class)
                    .hasMessage("Admins can't be deleted");
        }

Same thing applies for custom queries. Just try to test all your logic in your service-class

I hope this answers your question.

  • Related