couvq
couvq

Reputation: 53

Issue Mocking Spring Boot Repository with Mockito

I am an FEE brand new to the backend world and am building a practice project with Spring Boot. I have a service that uses a repository holding one "Admin" object with a username and password and the service has one method that validates whether the request has valid username/password for the repository. This service works when I test it with postman but for the life of me I cannot get the tests to work. I am using junit/mockito for the very first time so I think I am mocking my repository incorrectly. I have two log lines in the method of the service and looks like my test case when calling this method the repository username/password is not how I have it mocked but has the actual values of the username/password in the repository. This results in my test case failing. My goal is to have the mocked username/password for the repository being compared within my service class.

Here are the two log lines in my service's validateIsAdmin method: log.info("username and password for repository is: " + adminRepository.getAdminUserName() + " | " + adminRepository.getAdminPassword()); log.info("Recieved admin auth request with {}", adminRequest.getUsername() + " | " + adminRequest.getPassword());

Here is the service class I am trying to test:

package com.couvq.readinglist.service;

import com.couvq.readinglist.dto.AdminRequest;
import com.couvq.readinglist.dto.AdminResponse;
import com.couvq.readinglist.repository.AdminRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
@Log4j2
public class AdminAuthService {

    private final AdminRepository adminRepository;

    public AdminResponse validateIsAdmin(AdminRequest adminRequest) {
        log.info("username and password for repository is: " + adminRepository.getAdminUserName() + " | " + adminRepository.getAdminPassword());
        log.info("Recieved admin auth request with {}", adminRequest.getUsername() + " | " + adminRequest.getPassword());
        // if username and password of request matches that of repository, isAdmin is true
        if (adminRequest.getUsername().equals(adminRepository.getAdminUserName())
            && adminRequest.getPassword().equals(adminRepository.getAdminPassword())) {
            return AdminResponse.builder()
                    .isAdmin(true)
                    .build();
        } else {
            return AdminResponse.builder()
                    .isAdmin(false)
                    .build();
        }
    }
}

Here is my test case


import com.couvq.readinglist.dto.AdminRequest;
import com.couvq.readinglist.dto.AdminResponse;
import com.couvq.readinglist.repository.AdminRepository;
import com.couvq.readinglist.service.AdminAuthService;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;

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

    @Autowired
    private AdminAuthService adminAuthService;

    @Mock
    private AdminRepository adminRepository;

    @Test
    public void validateIsAdminWithAdminUserNameAndPasswordReturnsTrueResponse() {
        when(adminRepository.getAdminUserName()).thenReturn("username");
        when(adminRepository.getAdminPassword()).thenReturn("password");

        AdminRequest request = AdminRequest.builder()
                .username("username")
                .password("password")
                .build();

        AdminResponse response = adminAuthService.validateIsAdmin(request);

        AdminResponse expectedResponse = AdminResponse.builder()
                .isAdmin(true)
                .build();

        assertEquals(expectedResponse, response);
    }

}

Here is the output I got from my test assertion:

org.opentest4j.AssertionFailedError: 
Expected :AdminResponse(isAdmin=true)
Actual   :AdminResponse(isAdmin=false)

Does anyone have any suggestions as to how I can correctly mock this repository?

Upvotes: 0

Views: 1469

Answers (2)

Oleksandr Arzamastsev
Oleksandr Arzamastsev

Reputation: 31

Since it is a @SpringBootTest - the whole Application Context is bootstrapped, including the AdminRepository and AdminAuthService beans. If the test was a simple unit test, using the @Mock would be enough. But since it is an integration test, and the AdminAuthService is autowired into the test, we expect that the AdminRepository is injected into the AdminAuthService as well. To have the dependency injection working and being able to mock the AdminRepository we need to use the following:

@MockBean
AdminRepository adminRepository;

Furthermore, once you do this, the @ExtendWith(MockitoExtension.class) becomes redundant.

Upvotes: 0

Lee Greiner
Lee Greiner

Reputation: 1092

Simply stick with @ExtendWith(MockitoExtension.class) and replace @Autowired with @InjectMocks. This will inject your mock repository class into the service.

Upvotes: 1

Related Questions