2

我之前做过一些 TDD,但它们只是简单明了。

但是,我将实现一个 RESTful 客户端并调用第三方(Twitter 或 Jira)的一个 RESTful API。

我使用 Resteasy 客户端框架来实现它。代码是:

public void invokePUT() {
     ClientRequest request =
                 new ClientRequest("http://example.com/customers");
     request.accept("application/xml");
     ClientResponse<Customer> response = request.put(Customer.class); 
     try {
          if (response.getStatus() != 201)
               throw new RuntimeException("Failed!");
     } finally {
          response.releaseConnection(); 
     }}

如果我想为这个方法写一个测试(应该在实现这个方法之前写测试),我应该写什么样的代码。

对于 GET,我可以测试返回的实体是否等于我的预期实体,对于 POST,我可以测试创建的实体的 id 不为空。

但是 PUT 和 DELETE 怎么样。谢谢。

4

3 回答 3

2

尝试使用REST Assured测试框架。它是测试 REST 服务的绝佳工具。在他们的网站上,您会找到大量如何使用它的示例。只需将它与 JUnit 或 TestNG 一起使用来检查断言即可。

于 2012-05-08T21:38:49.243 回答
1

如果按预期调用 put 和 delete (使用预期参数等),我将注入测试的模拟类。easymock 或类似的东西对此有好处(与 post 和 get 相同)

编辑:如果您想测试其余客户端,请使用依赖注入来注入请求,然后使用 easymock 像这样模拟它(例如测试,如果删除被正确调用):

@Test void myTest(){
 ClientRequest mock = EasyMock.createMock(ClientRequest.class);
 mock.delete(2); //test if resource with id=2 is deleted or something similar

 EasyMock.replay(mock);
 invokeDelete(mock);
 EasyMock.verify(mock);
}
于 2012-05-08T14:04:07.340 回答
1

以下是我在短期内解决问题的方法:

1) 将请求提取为方法的参数。invokePUT()现在变成:

public void invokePUT(ClientRequest request) {
    request.accept("application/xml");
    ClientResponse<Customer> response = request.put(Customer.class); 
    try {
         if (response.getStatus() != 201)
              throw new RuntimeException("Failed!");
    } finally {
         response.releaseConnection(); 
    }
}

2)在您的测试中,使用存根版本ClientRequest

@Test
public void sendsPayloadAsXml() {
    StubbedClientRequest request = new StubbedClientRequest(new StubbedResponse());
    restApi.invokePUT(request);
    assertEquals("application/xml", request.acceptHeader);
}

@Test
public void makesTheCallUsingPut() {
    StubbedClientRequest request = new StubbedClientRequest(new StubbedResponse());
    restApi.invokePUT(request);
    assertTrue(request.putWasCalled);
}

@Test
public void releasesTheConnectionWhenComplete() {
    StubbedResponse success = new StubbedResponse();
    StubbedClientRequest request = new StubbedClientRequest(success);
    restApi.invokePUT(request);
    assertTrue(success.connectionWasClosed);
}

@Test(expected = RuntimeException.class)
public void raisesAnExceptionWhenInvalidResponseReceived() {
    StubbedClientRequest request = new StubbedClientRequest(new StubbedResponse(400));
    restApi.invokePUT(request);
}

private static class StubbedClientRequest extends ClientRequest {
    public String acceptHeader = "";
    public boolean putWasCalled;
    public ClientResponse response

    public StubbedRequest(ClientResponse response) {
        this.response = response;
    }

    @Override
    public ClientResponse put(Class klass) {
        putWasCalled = true;
        return response;
    }

    @Override
    public void accept(String header) {
        acceptHeader += header;
    }

}

private static class StubbedResponse extends ClientResponse {
    public boolean connectionWasReleased;
    public int status = 201;

    public StubbedResponse(int status) {
        this.status = status;
    }

    public StubbedResponse() { }
}

这可能不是一个完美的设计(将 ClientRequest 交给班级并将 RestEasy 的东西暴露给外界),但这是一个开始。

希望有帮助!

布兰登

于 2012-05-09T12:37:12.643 回答