【问题标题】:How to start with TDD for a RESTful api如何从 TDD 开始 RESTful api
【发布时间】:2011-10-17 08:25:50
【问题描述】:

我正在尝试练习 TDD 并有一个练习要做。 在互联网的某个地方部署了一个现有的服务,该服务具有公共 RESTful api。 对此 api 的每个请求都需要一些数据准备,例如有效的请求字符串构造、一些加密、一些正文消息格式等。 我想使用 TDD 为该服务编写通用客户端。

我知道这并不像例如StringCalculator kata,并且需要一些不同的方法。

我不知道如何开始。我想在不使用真实服务的情况下对其进行测试,因此需要一种虚假的 impl。编写一些假实现,将其部署在本地主机上并从我的测试中调用它会更好吗?或者可以模拟一个负责发送 http 请求的类?

我希望我的客户使用情况如下:

public class ServiceClientTest {
   @Test
   public void testSendStoreRequest() {
        ServiceClient client = new ServiceClient("app_key", "private_key")
        ClientResponse response = client.sendStoreRequest(StorageType.NORMAL,     "string_to_store");
       assertEquals("200", response.getStatus());
   } 
}

你能告诉我如何开始吗? 我应该从自下而上开始编写所有组件(用于创建请求字符串、用于加密等),然后在 ServiceClient 中全部使用它们,还是应该从自上而下和模拟的 ServiceClient 测试和实现开始?

【问题讨论】:

    标签: java tdd


    【解决方案1】:

    First of alldon't mock external APIs。为什么? Cos you don't own them.

    您的问题的理想解决方案似乎就是您开始描述的内容。您应该在您的项目中创建一个您拥有的接口,该接口将代表外部服务。

    public interface CalculatorService {
        int add(int a, int b);
    }
    

    这将是您进行测试的边界您的所有 UNIT 和 ACCEPTANCE 测试都应针对 CalculatorService 的模拟或存根运行。他们会很快。 您可以这样做,因为是您定义了合同(该接口的实际含义)。

    稍后,您将有一个用于远程 HTTP 休息服务的实现:

    class RemoteRestCalculator implements CalculatorService {
        public int add(int a, int b) {
            // call the remote service in here
        }
    }
    

    您需要测试此合同(边框)。因此,您将为RemoteRestCalculator 编写集成测试。您还可以进行一些端到端测试,使用RemoteRestCalculator 运行应用程序来测试接线等。

    现在,回答你的问题,如何测试RemoteRestCalculator

    1. 理想情况下,您应该在您的测试环境中部署一个真正的 http rest 服务实例,将其指向一个测试数据库等。 所以您与拥有该服务的人交谈,他们会为您提供 * .war 文件,然后您使用测试数据库等在本地部署它。有时他们会为您执行此操作,即该服务的“沙盒”部署。然后您为 RemoteRestCalculator 编写针对该实例运行的测试。
    2. 另一个解决方案与您提到的类似。创建一个“http rest 服务模拟器”。然后在本地部署。 诀窍在于,您必须为您在该模拟器中使用的所有功能复制真实的服务行为。因此,模拟器“添加”方法的行为必须与真实的相同。这个解决方案有很多优点和缺点。 然后您为 RemoteRestCalculator 编写针对该模拟器运行的测试。
    3. 有一种中途解决方案,业界普遍使用安静。您只需针对真实服务(或有时模拟器)的本地测试部署运行所有测试。 不幸的是,在这种情况下,当您有大量测试时,测试套件可能会非常慢。不推荐。Further reading about making builds go faster
    4. 还有另一种常用的解决方案,在大多数情况下不推荐使用。您创建了一个“http rest stub 类”,它的使用有点像 mockito mock,但它总是通过 http 进行通信。所以通常它会启动一个 http 服务器,你会在使用它之前启动它。它的缺点远多于优点。最大的缺点是服务的行为(外部依赖)分散在应用程序的许多测试中。 不推荐。

    【讨论】:

      【解决方案2】:

      我想这取决于...

      如果您认为您可能会将假 impl 用于其他测试等,那么这似乎是可行的方法,如果不只是模拟它的话。

      我会从模拟开始,看看它是如何发展的。

      【讨论】:

      • 所以你的意思是从 ServiceClient 开始并模拟所有依赖项,然后说 RequestBuilder 和 RequestSender 做同样的事情等等?然后用RequestSender调用原始服务的真实实现编写集成测试?
      • @grafthez 是的,您可能会发现您甚至可以在 ServiceClient 测试中使用真正的 Req Builder/Sender,但要模拟底层...取决于所涉及的复杂性。
      【解决方案3】:

      Or maybe mock a class responsible for sending http request?

      我认为这是要走的路。毕竟这是ServiceClient负责的:将请求转发给实际的服务。

      顺便说一句:想想用TDD来实现假服务,听起来有点奇怪。

      【讨论】:

      • 也许我会在针对真正的服务运行它之前,为某种集成测试构建一个假的。这可能很奇怪,但它会让我练习得更多。
      【解决方案4】:

      这可能会有所帮助 https://hackernoon.com/spring-boot-rest-tdd-from-scratch-15f13ed799e0 在本文中,您可以通过Spring Boot从头开始找到带有 spring 和 Rest api 的 TDD

      【讨论】:

        猜你喜欢
        • 2017-06-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-07
        • 1970-01-01
        • 2015-08-30
        相关资源
        最近更新 更多