如何使用mockito测试REST服务?

时间:2012-05-27 15:48:58

标签: java unit-testing rest mockito

我是Java Unit 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)。如果一切顺利,那么服务器应回复“您的架构已成功创建!”。

有人可以帮帮我吗?

5 个答案:

答案 0 :(得分:23)

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

您需要验证此方法是否符合此合同。

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

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

要做到这一点,您需要能够将initialize()注入您正在测试的对象中。它可以像以下方式重构对象一样简单:

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
    }
}

答案 1 :(得分:3)

你所说的听起来更像integration testing和Mockito(或任何其他模拟框架)对你没有多大用处。

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

我建议你阅读更多关于模拟/单元测试以及它应该用于哪种情况的内容。

答案 2 :(得分:2)

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

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

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

答案 3 :(得分:1)

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

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

singleton

答案 4 :(得分:0)

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

(使用球衣1.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

}