如何使用 mockito 来测试 REST 服务?

2022-09-01 14:34:27

我是Java单元测试的新手,我听说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();
    }

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

有人可以帮我吗?


答案 1

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

并且您需要验证该方法是否履行了此合同。

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

Mockito 可以通过模拟对 的依赖关系来提供帮助:您可以创建一个 mock of ,并验证当您在测试中调用方法时,是否确实使用适当的实体参数调用了此 mock。DataStoreServiceDataStoreServiceinitialize()

为此,您需要能够将 注入到所测试的对象中。它可以像按以下方式重构对象一样简单: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<Entity> argument = ArgumentCaptor.forClass(Entity.class);
    verify(mock).put(argument.capture());
    assertEquals("the correct kind", argument.getValue().getKind());
    // ... other assertions
}

答案 2

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

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

我建议你阅读更多关于模拟/单元测试的信息,以及它应该在什么情况下使用。


推荐