3

製品をテキスト ファイルとしてディスクに保存する必要がある TDD アプローチを使用して、以下の方法で WCF を使用して JSON 形式で安らかな Web サービスを作成するタスクが与えられました。

CreateProduct(Product product)
GetAProduct(int productId) 


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

サービスとその Web メソッドの作成は簡単ですが、

TDD でこのタスクにどのように取り組みますか? SUT コードを作成する前に、テストを作成する必要があります。

単体テストのルールには、独立していて反復可能であるべきだとも書かれています。

以下のように、多くの混乱と問題があります。

1) 実際のサービスの実装に対して参照を追加するか、サービスの URL に対してユニット テストを作成する必要がありますか (この場合、サービスをホストして実行する必要があります)。または両方?

2) 1 つのアプローチとして、製品を作成するテスト メソッドを 1 つ作成し、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

あなたの質問に答えるには、RESTサービスを呼び出すテストを作成し、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}");
        }
    }

これはあなたが書くことを検討するかもしれないテストの1つです。

[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 に答える