如何使用mockito测试REST服务?

我是Javaunit testing的新手,我听说Mockito框架非常适合测试目的。

我开发了一个REST服务器(CRUD方法),现在我想测试它,但我不知道怎么做?

更多我不知道这个测试程序应该如何开始。 我的服务器应该在localhost上工作,然后在该url上调用(例如localhost:8888)?

这是我到目前为止所尝试的,但我很确定这不是正确的方法。

@Test public void testInitialize() { RESTfulGeneric rest = mock(RESTfulGeneric.class); ResponseBuilder builder = Response.status(Response.Status.OK); builder = Response.status(Response.Status.OK).entity( "Your schema was succesfully created!"); when(rest.initialize(DatabaseSchema)).thenReturn(builder.build()); String result = rest.initialize(DatabaseSchema).getEntity().toString(); System.out.println("Here: " + result); assertEquals("Your schema was succesfully created!", result); } 

这是initialize方法的代码。

  @POST @Produces(MediaType.APPLICATION_JSON) @Path("/initialize") public Response initialize(String DatabaseSchema) { /** Set the LogLevel to Info, severe, warning and info will be written */ LOGGER.setLevel(Level.INFO); ResponseBuilder builder = Response.status(Response.Status.OK); LOGGER.info("POST/initialize - Initialize the " + user.getUserEmail() + " namespace with a database schema."); /** Get a handle on the datastore itself */ DatastoreService datastore = DatastoreServiceFactory .getDatastoreService(); datastore.put(dbSchema); builder = Response.status(Response.Status.OK).entity( "Your schema was succesfully created!"); /** Send response */ return builder.build(); } 

在这个测试用例中,我想将一个Json字符串发送到服务器(POST)。 如果一切顺利,那么服务器应回复“您的架构已成功创建!”。

有人可以帮帮我吗?

好。 因此,该方法的契约如下:将输入字符串解析为JSON,如果它无效则发送回BAD_REQUEST 。 如果它有效,请在datastore创建具有各种属性的实体(您知道它们),然后发送回OK

您需要validation该方法是否满足此合同。

Mockito在哪里帮忙? 好吧,如果你在没有Mockito的情况下测试这个方法,你需要一个真正的DataStoreService ,你需要validation在这个真正的DataStoreService是否已经正确创建了实体。 这是您的测试不再是unit testing的地方,而且这也是测试太复杂,太长,太难以运行的地方,因为它需要复杂的环境。

Mockito可以通过模拟对DataStoreService的依赖来提供帮助:您可以创建DataStoreService的模拟,并在测试中调用initialize()方法时validation是否使用适当的实体参数调用了此模型。

为此,您需要能够将DataStoreService注入到测试对象中。 它可以像以下方式重构对象一样简单:

 public class MyRestService { private DataStoreService dataStoreService; // constructor used on the server public MyRestService() { this.dataStoreService = DatastoreServiceFactory.getDatastoreService(); } // constructor used by the unit tests public MyRestService(DataStoreService dataStoreService) { this.dataStoreService = dataStoreService; } public Response initialize(String DatabaseSchema) { ... // use this.dataStoreService instead of datastore } } 

现在在您的测试方法中,您可以:

 @Test public void testInitializeWithGoodInput() { DataStoreService mockDataStoreService = mock(DataStoreService.class); MyRestService service = new MyRestService(mockDataStoreService); String goodInput = "..."; Response response = service.initialize(goodInput); assertEquals(Response.Status.OK, response.getStatus()); ArgumentCaptor argument = ArgumentCaptor.forClass(Entity.class); verify(mock).put(argument.capture()); assertEquals("the correct kind", argument.getValue().getKind()); // ... other assertions } 

您所谈论的内容听起来更像是集成测试 ,Mockito(或任何其他模拟框架)对您没有多大用处。

如果你想要编写你编写的测试代码,Mockito肯定是一个有用的工具。

我建议你阅读更多关于模拟/unit testing以及应该在哪些情况下使用的内容。

Mockito(通常)用于测试部分代码; 例如,如果您正在使用REST服务,但又不想进行全栈测试,那么您将模拟连接到REST服务的服务,从而允许您精确且一致地测试特定行为。

要在不命中数据库的情况下测试REST服务的内部部分(例如,特定服务方法),您将模拟数据库子系统,仅允许测试服务内部,而不涉及数据库。 此测试属于REST服务模块,而不是客户端。

要测试REST服务本身,您需要使用实际的客户端库,创建一个完整的堆栈集成测试。 Mockito可用于模拟与REST服务消耗无关的客户端部分。

最好的方法是使用wiremock添加以下依赖项com.github.tomakehurst wiremock 2.4.1 org.igniterealtime.smack smack-core 4.0.6

定义并使用线缆,如下所示

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

我同意这不是unit testing而是集成测试,无论如何你更喜欢看看jersey和嵌入式灰熊服务器测试。 总结一下,这段代码在localhost:8888启动了grizzly服务器(也可以启动数据库),然后设置客户端的jersey的客户端并发出POST请求,应该测试响应。 这是一个集成,因为您正在测试服务器和数据库,您可以使用mockito来模拟数据库,但这取决于您的服务器和数据库是如何绑定的。

(使用jersey1.11和灰熊2.2进行测试)

  @BeforeClass public static void setUpClass() throws Exception { // starts grizzly Starter.start_grizzly(true); Thread.sleep(4000); } @Before public void setUp() throws Exception { client = new Client(); webResource = client.resource("http://localhost:8888"); } @Test public void testPostSchemaDatabase() throws Exception { { String DatabaseSchema = "{ database_schema : {...}}"; logger.info("REST client configured to send: " + DatabaseSchema); ClientResponse response = webResource .path("/initialize") .type("application/json") .post(ClientResponse.class, DatabaseSchema); //wait for the server to process Thread.sleep(2000); assertEquals(response.getStatus(), 204); //test the response } } @After public void after() throws JSONException { //probably you want to delete the schema at database and stop the server }