为了账号安全,请及时绑定邮箱和手机立即绑定

使用 mockmvc 进行测试时无法模拟存储库

使用 mockmvc 进行测试时无法模拟存储库

蝴蝶刀刀 2023-05-24 15:59:58
我有这个非常简单的控制器类和一个简单的 (jpa) 存储库。我想要做的是测试它的 api 但模拟它的存储库并让它根据测试用例返回或不返回对象。我现在的问题是我不知道该怎么做。我知道如何模拟存储库并将其注入控制器/服务类 @Mock / @InjectMocks / when().return()但是当我在用 MockMvc 发出请求后想做同样的事情时,我失败了。非常感谢任何帮助控制器import java.util.Optional;@RestController@Slf4jpublic class ReceiptController implements ReceiptsApi {    @Autowired    private ReceiptRepository receiptRepository;    @Autowired    private ErrorResponseExceptionFactory exceptionFactory;    @Autowired    private ApiErrorResponseFactory errorResponseFactory;    @Override    public Receipt getReceipt(Long id) {        Optional<ReceiptEntity> result = receiptRepository.findById(id);        if (result.isEmpty()) {            throw invalid("id");        }        ReceiptEntity receipt = result.get();        return Receipt.builder().id(receipt.getId()).purchaseId(receipt.getPurchaseId()).payload(receipt.getHtml()).build();    }    private ErrorResponseException invalid(String paramName) {        return exceptionFactory.errorResponse(                errorResponseFactory.create(HttpStatus.NOT_FOUND.value(), "NOT_VALID", String.format("receipt with id %s not found.", paramName))        );    }}而且是测试课@WebMvcTest(ReceiptController.class)@RestClientTestpublic class ReceiptControllerTest {    @InjectMocks    private ReceiptController receiptController;    @Mock    private ReceiptRepository receiptRepository;    @Mock    private ErrorResponseExceptionFactory exceptionFactory;    @Mock    private ApiErrorResponseFactory errorResponseFactory;    private MockMvc mvc;    @Before    public void setUp() {        MockitoAnnotations.initMocks(this);        mvc = MockMvcBuilders.standaloneSetup(                new ReceiptController())                      .build();    }
查看完整描述

2 回答

?
哈士奇WWW

TA贡献1799条经验 获得超6个赞

在您的setUp()方法中,您正在使用 Mockito 来模拟带有注释的 bean,@Mock并将它们注入到 的新实例中ReceiptController,然后将其放入带有注释的字段中@InjectMocks

ReceiptController在下一行中,您将使用(您使用的)的新实例设置 MockMvc new ReceiptController(),而不是使用 Mockito 创建的实例。这意味着该实例中的所有字段都将是null.

这几乎可以归结为Why is my Spring @Autowiredfieldnull


要解决这个问题,您可以传递receiptController给 MockMvc。在这种情况下,您还可以删除@WebMvcTest@RestClientTest因为您不使用它们。

或者,您可以使用 设置测试,并通过使用in stead of和in stead of@RunWith(SpringRunner.class)正确设置 Spring 测试。在这种情况下,您根本不需要方法,因为 MockMvc 可以由 Spring 自动装配。@Autowired@InjectMocks@MockBean@MocksetUp()


查看完整回答
反对 回复 2023-05-24
?
小怪兽爱吃肉

TA贡献1852条经验 获得超1个赞

允许您进行集成测试,而不是单元测试。

它们允许您启动实际的 Spring 应用程序(使用随机端口)并测试实际的控制器类及其依赖项。这意味着您在测试顶部声明的变量实际上并未在当前设置中使用。

如果你想对你的控制器进行单元测试,你可以删除@WebMvcTest,创建模拟依赖项(就像你所做的那样)并直接调用你的方法而不是使用 MockMvc。

如果你真的想写一个集成测试,你需要模拟你的外部依赖(例如数据库)。你可以配置spring在测试环境中使用嵌入式数据库(例如H2),这样就不会影响你的真实数据库。

查看完整回答
反对 回复 2023-05-24
  • 2 回答
  • 0 关注
  • 129 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信