我被赋予了一项任务,即使用WCF格式化JSON格式化,使用以下方法使用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()事件中,我只删除已创建的产品。
但我与上述问题的关系是
如果我为每个Web方法创建一个单独的单元测试,然后例如调用GetAProduct()web方法,我必须将一些测试数据物理存储在服务器上,因为它不能依赖于CreateProduct()单元测试。他们应该能够独立运作。
请建议。
谢谢,
答案 0 :(得分:0)
很好地回答你的问题我要做的是编写测试调用其余服务并使用类似Rhino Mocks的东西来安排(即设置对调用的期望),act(实际运行调用单元的代码)进行测试并断言你得到了你期望的结果。你可以模拟其余调用的预期结果。从前到后对剩余服务的实际测试将是集成测试,而不是单元测试。
所以更清楚的是,您需要编写的单元测试是围绕实际调用业务逻辑中的其余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();
}
}
答案 1 :(得分:0)
我建议不要担心网络服务的终点并关注系统的行为。为了便于讨论,我将删除所有技术术语,并谈谈我认为您正在尝试解决的核心业务问题:创建产品目录。
为了做到这一点,首先要考虑产品目录的作用,而不是关于如何做的技术细节。将其作为测试的起点。
public class ProductCatalogTest
{
[Test]
public void allowsNewProductsToBeAdded() {}
[Test]
public void allowsUpdatesToExistingProducts() {}
[Test]
public void allowsFindingSpecificProductsUsingSku () {}
}
我不会在这里详细介绍如何实施测试和生产代码,但这是一个起点。一旦您完成ProductCatalog
生产课程,您就可以将注意力转向技术细节,例如制作网络服务和整理您的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
中包含的业务逻辑,并且可能会跳过测试编组,因为它可能完全由框架完成,并且只需要很少的代码就可以将控制器绑定到产品目录中。您的里程可能会有所不同。
最后,在测试驱动目录时,我希望代码可以分成多个类,并且模拟在那里发挥作用,因此它们将进行单元测试,而不是大型集成测试。再一次,这是另一天的主题。
希望有所帮助!
布兰登