33 java rest unit-testing spring-test
假设我在我的应用程序中创建了一个使用远程Web服务的简单客户端,该服务在某个URI上公开RESTful API /foo/bar/{baz}.现在我想对我的客户端进行单元测试,该客户端调用此Web服务.
理想情况下,在我的测试中,我想模拟我从Web服务获得的响应,给出一个特定的请求,如/foo/bar/123或/foo/bar/42.我的客户端假设API实际上正在某个地方运行,所以我需要一个本地"Web服务"来开始运行http://localhost:9090/foo/bar我的测试.
我希望我的单元测试是自包含的,类似于使用Spring MVC Test框架测试Spring控制器.
一些简单客户端的伪代码,从远程API获取数字:
// Initialization logic involving setting up mocking of remote API at
// http://localhost:9090/foo/bar
@Autowired
NumberClient numberClient // calls the API at http://localhost:9090/foo/bar
@Test
public void getNumber42() {
onRequest(mockAPI.get("/foo/bar/42")).thenRespond("{ \"number\" : 42 }");
assertEquals(42, numberClient.getNumber(42));
}
// ..
Run Code Online (Sandbox Code Playgroud)
使用Spring有哪些替代方案?
Tun*_*uno 16
如果您使用Spring RestTemplate,则可以使用MockRestServiceServer.可以在这里找到一个例子https://objectpartners.com/2013/01/09/rest-client-testing-with-mockrestserviceserver/
小智 13
最好的方法是使用WireMock.添加以下依赖项:
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
<version>2.4.1</version>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack</groupId>
<artifactId>smack-core</artifactId>
<version>4.0.6</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)
定义并使用线缆如下所示
@Rule
public WireMockRule wireMockRule = new WireMockRule(8089);
String response ="Hello world";
StubMapping responseValid = stubFor(get(urlEqualTo(url)).withHeader("Content-Type", equalTo("application/json"))
.willReturn(aResponse().withStatus(200)
.withHeader("Content-Type", "application/json").withBody(response)));
Run Code Online (Sandbox Code Playgroud)
您可以轻松地使用Mockito在Spring Boot 中模拟 REST API 。
在您的测试树中放置一个存根控制器:
@RestController
public class OtherApiHooks {
@PostMapping("/v1/something/{myUUID}")
public ResponseEntity<Void> handlePost(@PathVariable("myUUID") UUID myUUID ) {
assert (false); // this function is meant to be mocked, not called
return new ResponseEntity<Void>(HttpStatus.NOT_IMPLEMENTED);
}
}
Run Code Online (Sandbox Code Playgroud)
运行测试时,您的客户端需要在本地主机上调用 API 。这可以在src/test/resources/application.properties. 如果测试正在使用RANDOM_PORT,则您的被测客户端将需要找到该值。这有点棘手,但问题在这里得到解决:Spring Boot - How to get the running port
将您的测试类配置为使用WebEnvironment(正在运行的服务器),现在您的测试可以以标准方式使用 Mockito,ResponseEntity根据需要返回对象:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class TestsWithMockedRestDependencies {
@MockBean private OtherApiHooks otherApiHooks;
@Test public void test1() {
Mockito.doReturn(new ResponseEntity<Void>(HttpStatus.ACCEPTED))
.when(otherApiHooks).handlePost(any());
clientFunctionUnderTest(UUID.randomUUID()); // calls REST API internally
Mockito.verify(otherApiHooks).handlePost(eq(id));
}
}
Run Code Online (Sandbox Code Playgroud)
您还可以使用它在上面创建的模拟环境中对整个微服务进行端到端测试。一种方法是注入TestRestTemplate您的测试类,并使用它来调用您的REST API,而不是clientFunctionUnderTest从示例中调用。
@Autowired private TestRestTemplate restTemplate;
@LocalServerPort private int localPort; // you're gonna need this too
Run Code Online (Sandbox Code Playgroud)
因为OtherApiHooks是@RestController在测试树中,Spring Boot 在运行时会自动建立指定的 REST 服务SpringBootTest.WebEnvironment。
Mockito 在这里用于模拟控制器类——而不是整个服务。因此,在mock被命中之前会有一些由Spring Boot管理的服务器端处理。这可能包括反序列化(和验证)示例中显示的路径 UUID 之类的事情。
据我所知,这种方法对于 IntelliJ 和 Maven 的并行测试运行是稳健的。
| 归档时间: |
|
| 查看次数: |
60131 次 |
| 最近记录: |