猿问

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

我有这个非常简单的控制器类和一个简单的 (jpa) 存储库。我想要做的是测试它的 api 但模拟它的存储库并让它根据测试用例返回或不返回对象。


我现在的问题是我不知道该怎么做。


我知道如何模拟存储库并将其注入控制器/服务类 @Mock / @InjectMocks / when().return()


但是当我在用 MockMvc 发出请求后想做同样的事情时,我失败了。非常感谢任何帮助


控制器



import java.util.Optional;


@RestController

@Slf4j

public 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)

@RestClientTest

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

    }



蝴蝶刀刀
浏览 176回答 2
2回答

哈士奇WWW

在您的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()

小怪兽爱吃肉

允许您进行集成测试,而不是单元测试。它们允许您启动实际的 Spring 应用程序(使用随机端口)并测试实际的控制器类及其依赖项。这意味着您在测试顶部声明的变量实际上并未在当前设置中使用。如果你想对你的控制器进行单元测试,你可以删除@WebMvcTest,创建模拟依赖项(就像你所做的那样)并直接调用你的方法而不是使用 MockMvc。如果你真的想写一个集成测试,你需要模拟你的外部依赖(例如数据库)。你可以配置spring在测试环境中使用嵌入式数据库(例如H2),这样就不会影响你的真实数据库。
随时随地看视频慕课网APP

相关分类

Java
我要回答