Java 集成测试中MockMvc和RestTemplate的区别

Java 集成测试中MockMvc和RestTemplate的区别,java,spring,spring-mvc,junit,integration-testing,Java,Spring,Spring Mvc,Junit,Integration Testing,和都用于与Spring和JUnit的集成测试 问题是:它们之间有什么区别?我们什么时候应该选择它们 以下是两个选项的示例: //MockMVC example mockMvc.perform(get("/api/users")) .andExpect(status().isOk()) (...) //RestTemplate example ResponseEntity<User> entity = restTemplate.exch

和都用于与Spring和JUnit的集成测试

问题是:它们之间有什么区别?我们什么时候应该选择它们

以下是两个选项的示例:

//MockMVC example
mockMvc.perform(get("/api/users"))
            .andExpect(status().isOk())
            (...)

//RestTemplate example
ResponseEntity<User> entity = restTemplate.exchange("/api/users",
            HttpMethod.GET,
            new HttpEntity<String>(...),
            User.class);
assertEquals(HttpStatus.OK, entity.getStatusCode());
//MockMVC示例
mockMvc.perform(get(“/api/users”))
.andExpect(状态().isOk())
(...)
//RestTemplate示例
ResponseEntity=restemplate.exchange(“/api/users”,
HttpMethod.GET,
新的HttpEntity(…),
用户类别);
assertEquals(HttpStatus.OK,entity.getStatusCode());

使用
MockMvc
,您通常会设置整个web应用程序上下文并模拟HTTP请求和响应。因此,尽管一个假的DispatcherServlet正在启动和运行,模拟MVC堆栈的工作方式,但没有真正的网络连接

使用
restemplate
,您必须部署一个实际的服务器实例来侦听您发送的HTTP请求。

如中所述 文章当您想测试应用程序的服务器端时,应该使用
MockMvc

SpringMVC测试建立在来自
SpringTest
的模拟请求和响应之上,不需要运行的servlet容器。主要区别在于,实际的SpringMVC配置是通过TestContext框架加载的,请求是通过实际调用
DispatcherServlet
和运行时使用的所有相同的SpringMVC基础结构来执行的

例如:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration("servlet-context.xml")
public class SampleTests {

  @Autowired
  private WebApplicationContext wac;

  private MockMvc mockMvc;

  @Before
  public void setup() {
    this.mockMvc = webAppContextSetup(this.wac).build();
  }

  @Test
  public void getFoo() throws Exception {
    this.mockMvc.perform(get("/foo").accept("application/json"))
        .andExpect(status().isOk())
        .andExpect(content().mimeType("application/json"))
        .andExpect(jsonPath("$.name").value("Lee"));
  }}
当您想要测试Rest客户端应用程序时,应该使用
RestTemplate

如果您有使用RestTemplate的代码,您可能需要对其进行测试,并可以针对正在运行的服务器或模拟RestTemplate。客户端REST测试支持提供了第三种选择,即使用实际的
RestTemplate
,但将其配置为自定义的
ClientHttpRequestFactory
,该工厂根据实际请求检查期望并返回存根响应

例如:

RestTemplate restTemplate = new RestTemplate();
MockRestServiceServer mockServer = MockRestServiceServer.createServer(restTemplate);

mockServer.expect(requestTo("/greeting"))
  .andRespond(withSuccess("Hello world", "text/plain"));

// use RestTemplate ...

mockServer.verify();

另请阅读

可以同时使用RestTemplate和MockMvc

如果您有一个单独的客户机,其中已经完成了Java对象到URL的繁琐映射以及Json的转换,并且希望在MockMVC测试中重用这些映射,那么这将非常有用

以下是如何做到这一点:

@RunWith(SpringRunner.class)
@ActiveProfiles("integration")
@WebMvcTest(ControllerUnderTest.class)
public class MyTestShould {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void verify_some_condition() throws Exception {

        MockMvcClientHttpRequestFactory requestFactory = new MockMvcClientHttpRequestFactory(mockMvc);
        RestTemplate restTemplate = new RestTemplate(requestFactory);

        ResponseEntity<SomeClass> result = restTemplate.getForEntity("/my/url", SomeClass.class);

        [...]
    }

}
@RunWith(SpringRunner.class)
@ActiveProfiles(“集成”)
@WebMvcTest(ControllerUnderTest.class)
公共类MyTestShould{
@自动连线
私有MockMvc-MockMvc;
@试验
public void verify_some_condition()引发异常{
MockMvcClientHttpRequestFactory requestFactory=新的MockMvcClientHttpRequestFactory(mockMvc);
RestTemplate RestTemplate=新的RestTemplate(requestFactory);
ResponseEntity result=restemplate.getForEntity(“/my/url”,SomeClass.class);
[...]
}
}

对于我的用例,我认为这是最好的方法,因为RestTemplate使响应的ORM映射在HATEOS(特别是)开始使用时更加简单。@fquinner,但它不能回滚,因为它的行为类似于客户端,并且在不同的线程中运行,所以回滚是不可能的。您需要维护另一个testDb,然后在哪里准备名为
Lee
的模拟实体?我认为
andExpect(jsonPath($.name”).value(“Lee”)
验证将失败。@naXa,这些是集成测试,因此我们假设相应的数据存储在数据库中或在测试之前填充。SpringMVC只测试“mock”servlet容器,但使用真实bean、db连接等构建应用程序上下文。但是,mockmvc无法处理存储在文件中的自定义异常(用于测试负面场景)。它被测试用例函数的“抛出异常”捕获。如何在MockMvc中处理这个问题?