Spring Boot 使用Mockito模拟Sping Boot 存储库问题

r8uurelv  于 2022-12-12  发布在  Spring
关注(0)|答案(2)|浏览(209)

我是一个后端世界的FEE新手,正在用Sping Boot 构建一个实践项目。我有一个服务,它使用一个存储库保存一个带有用户名和密码的“Admin”对象,该服务有一个方法来验证请求是否具有存储库的有效用户名/密码。当我用postman测试时,这个服务工作正常,但我的生命中我无法让测试工作。我是第一次使用junit/mockito,所以我想我是在错误地模拟我的仓库。我在服务的方法中有两个日志行,看起来像我的测试用例,当调用这个方法时,仓库用户名/密码不是我模拟的,而是仓库中用户名/密码的实际值。这导致我的测试用例失败。我的目标是让 * 在我的服务类中比较的存储库的mock * 用户名/密码。
下面是我的服务的validateIsAdmin方法中的两个日志行:log.info("username and password for repository is: " + adminRepository.getAdminUserName() + " | " + adminRepository.getAdminPassword()); log.info("Recieved admin auth request with {}", adminRequest.getUsername() + " | " + adminRequest.getPassword());
下面是我尝试测试的服务类:

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();
        }
    }
}

这是我的测试案例

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);
    }

}

下面是我从测试Assert中得到的输出:

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

有人对我如何正确地模拟这个存储库有什么建议吗?

mmvthczy

mmvthczy1#

只需使用@ExtendWith(MockitoExtension.class)并将@Autowired替换为@InjectMocks,这将把您的mock存储库类注入到服务中。

oug3syen

oug3syen2#

因为它是一个@SpringBootTest-整个Application Context都是 Bootstrap 的,包括AdminRepositoryAdminAuthService bean。如果测试是一个简单的单元测试,使用@Mock就足够了。但是因为它是一个集成测试,并且AdminAuthService是自动连接到测试中的,我们希望AdminRepository也被注入到AdminAuthService中。为了使依赖注入工作并能够模拟AdminRepository,我们需要使用以下代码:

@MockBean
AdminRepository adminRepository;

此外,一旦这样做,@ExtendWith(MockitoExtension.class)就变得多余了。

相关问题