3

我的任务是使用 WCF 创建一个带有 JSON 格式的宁静 Web 服务,并使用以下方法使用 TDD 方法,该方法应将产品作为文本文件存储在磁盘上:

CreateProduct(Product product)
GetAProduct(int productId) 


URI Templates:
POST to /MyService/Product
GET to /MyService/Product/{productId}

创建服务及其 Web 方法很容易,但

您将如何使用 TDD 完成这项任务?您应该在创建 SUT 代码之前创建一个测试。

单元测试的规则说它们也应该是独立的和可重复的。

我有一些困惑和问题如下:

1)我应该通过添加对实际服务实现的引用还是针对服务的 url 编写单元测试(在这种情况下,我必须托管和运行服务)?或两者?

2) 我在想一种方法可能只是创建一个测试方法,在其中创建产品,调用 CreateProduct() 方法,然后调用 GetAProduct() 方法并断言发送的产品是我收到的产品. 在 TearDown() 事件中,我只是删除了创建的产品。

但我对上述问题的看法是

  • 它测试了多个功能,因此它不是真正的单元测试。
  • 它不检查数据是否正确存储在文件中
  • 是TDD吗?

如果我为每个 web 方法创建一个单独的单元测试,例如调用 GetAProduct() web 方法,我必须将一些测试数据物理存储在服务器上,因为它不能依赖 CreateProduct() 单元测试。他们应该能够独立运行。

请指教。

谢谢,

4

2 回答 2

1

我建议不要担心 Web 服务端点,而是关注系统的行为。为了便于讨论,我将抛开所有技术术语,谈谈我认为您要解决的核心业务问题:创建产品目录。

为了做到这一点,首先要考虑产品目录的作用,而不是关于如何做的技术细节。将其用作测试的起点。

public class ProductCatalogTest
{
    [Test]
    public void allowsNewProductsToBeAdded() {}

    [Test]
    public void allowsUpdatesToExistingProducts() {}

    [Test]
    public void allowsFindingSpecificProductsUsingSku () {}
}

我不会在这里详细介绍如何实现测试和生产代码,但这是一个起点。一旦完成了ProductCatalog生产类,您就可以将注意力转向技术细节,例如制作 Web 服务和编组 JSON。

我不是 .NET 人,所以这主要是伪代码,但它可能最终看起来像这样。

public class ProductCatalogServiceTest
{
   [Test]
   public void acceptsSkuAsParameterOnGetRequest()
   {
       var mockCatalog = new MockProductCatalog(); // Hand rolled mock here.
       var catalogService = new ProductCatalogService(mockCatalog);

       catalogService.find("some-sku-from-url")

       mockCatalog.assertFindWasCalledWith("some-sku-from-url");
   }

   [Test]
   public void returnsJsonFromGetRequest()
   {
       var mockCatalog = new MockProductCatalog(); // Hand rolled mock here.
       mockCatalog.findShouldReturn(new Product("some-sku-from-url"));
       var mockResponse = new MockHttpResponse(); // Hand rolled mock here.

       var catalogService = new ProductCatalogService(mockCatalog, mockResponse);

       catalogService.find("some-sku-from-url")

       mockCatalog.assertWriteWasCalledWith("{ 'sku': 'some-sku-from-url' }");
   }
}

您现在已经进行了端到端的测试,并测试了整个过程。我个人会测试驱动包含在其中的业务逻辑,ProductCatalog并且可能会跳过测试编组,因为无论如何它都可能由框架完成,并且只需很少的代码即可将控制器绑定到产品目录中。你的旅费可能会改变。

最后,在测试驱动目录时,我希望代码被拆分为多个类并在那里进行模拟,因此它们将进行单元测试,而不是大型集成测试。同样,这是另一天的话题。

希望有帮助!

布兰登

于 2012-12-10T19:12:18.077 回答
0

为了回答你的问题,我要做的是编写调用其余服务的测试并使用 Rhino Mocks 之类的东西来安排(即设置调用的期望),行动(实际运行调用要测试的单元的代码和断言你得到你期望的结果。你可以模拟出rest调用的预期结果。从前到后对rest服务的实际测试将是集成测试而不是单元测试。

因此,为了更清楚,您需要编写的单元测试是围绕业务逻辑中实际调用其余 Web 服务的测试......

就像这是您提出的实现(让我们假设这甚至还没有被编写)

public class SomeClass
    {
        private IWebServiceProxy proxy;
        public SomeClass(IWebServiceProxy proxy)
        {
            this.proxy = proxy;
        }

        public void PostTheProduct()
        {
            proxy.Post("/MyService/Product");
        }

        public void REstGetCall()
        {
            proxy.Get("/MyService/Product/{productId}");
        }
    }

这是您可能考虑编写的测试之一。

[TestFixture]
    public class TestingOurCalls()
    {
        [Test]
        public Void TestTheProductCall()  
        {    
        var webServiceProxy = MockRepository.GenerateMock<IWebServiceProxy>();
        SomeClass someClass = new SomeClass(webServiceProxy);

        webServiceProxy.Expect(p=>p.Post("/MyService/Product"));

        someClass.PostTheProduct(Arg<string>.Is.Anything());

        webServiceProxy.VerifyAllExpectations();

       }

}

于 2012-12-08T18:32:46.883 回答