web-dev-qa-db-ja.com

ユニットテストクラスのベストプラクティス。主に依存関係のメソッドの呼び出しを担当しますが、ロジックも含まれます

必要なファイルを含むファイルを作成する責任があるStartCommandHandlerがあるとしましょう。しかし、これを行うには、次のような一連の副責任を与える必要があります。

  • FTPにファイルが存在するかどうかを確認します
  • 複数のソースから一時フォルダにファイルをダウンロードしない場合
  • 次に、フォルダ内のスクリプトを実行します
  • 次に、スクリプトの実行後に生成されたファイルを読み取ります
  • 次に、そのフォルダからZipを作成します
  • 次に、そのフォルダを削除します
  • 次に、データベースを更新します

そのコマンドハンドラーの結果として、必要なすべてのファイルを含むフォルダーを作成しています。これで、そのフォルダーは別の操作の準備ができました。

今読んだところ"Art of the Unit testing"。そしてユニットテストを追加し始めました。私もSOLIDの原則に従いました。特にSRPDIPは、私の意見では単体テストの前提条件です。したがって、上で述べたほとんどのことは特定のインターフェースで行われます。したがって、そのコマンドハンドラーの90%の仕事は、依存関係のメソッドを呼び出すことです。そして、10%はこのようなロジックです:

if(!_dependency1.IsAnySomething())
{
     _dependency2.Download();

      var isScriptNeeded = _dependency2.IsScriptNeeded();

      if(isScriptNeeded)
      {
          var res = _dependency3.ExecuteScript();
         _dependency4.SetScriptResult(res.Info, res.Date, res.State);
      }

     _dependency3.Archive();

     _dependency5.DeleteTemp();
}

そのコマンドハンドラの依存関係はすべてテスト済みです。しかし、hatコマンドハンドラーには、ダウンロードファイルが必要か、一時ファイルが削除されたかなど、いくつかの小さなロジックも含まれています...

次のような質問がたくさんあります。

  1. ユニットテストはそのようなユニットには意味がありませんか?統合テストは救いに?なぜなら、ダウンロード後にDeleteTempが呼び出されるか、スクリプトが実行されるか、またはスクリプトの結果が正しい方法で渡されるSetScriptResultメソッド。それは良いユニットテストですか?
  2. テスト可能にするためにそのクラスをリファクタリングする方法はありますか?

更新;

これは他のものを呼び出して調整する責任があるため、すべての依存関係を調べて、必要なだけ何度でも正しい順序で呼び出されていることを確認できます。 MoqがモッククラスのVerifyメソッドで提供するようなもの。

        // Explicitly verify each expectation...
        mockSomeClass.Verify(s => s. SetScriptResult(It.IsAny<YourType>()/* or whatever value parameters you may setup snd ecpect it to be called*/), Times.Once());

https://stackoverflow.com/a/9136721/2663492

ユニットテストの責任は他の相互接続されたユニットが適切に機能していることを前提としてユニットをテストすることであり、ユニットテストはほんの一瞬で完了する必要があるため、ここで行ってここで述べたことで十分です。または、チームメイトがいくつかの変更を加えた場合、この変更が既存の機能に影響を与えていないかどうかをすぐに確認できるので、すぐに行って、UTの深刻な要件になります。

そうは言っても、あなたがやりたいことは、これらすべてのユニットが確実にゲル化し、一緒にうまく機能することです。これは、この機能が機能するかどうかを確認するためにいくつかの統合テストが必要になる可能性があることを示唆しています。

システムの複雑さ、並列ユーザーの数、要件などに応じて、負荷テストが必要かどうかを判断できます。

テクニックとして単体テストについて話していることを強調しておきます。ツール/メディアとして単体テストツールを使用して、統合テストと負荷テストを作成できます。問題や解決策の実例をよりよく描き、実証するのに役立つ、IMHOのSpecflowなどのBDDフレームワークを確認することをお勧めします。 (プロセスではなくメディアとしてのBDDフレームワークも同様です。)

0
Amin Mirzapour

2つのifステートメントがあります。コードがifステートメントに基づいて正しい依存関係メソッドを呼び出すかどうかをテストする必要があります。

順次メソッド呼び出しをテストするのは間違っているように見えるかもしれません。その場合は、より悪いケースをカバーすることをお勧めします。たとえば、_dependency2.Download();が例外をスローするとどうなりますか?その後

__dependency3.Archive();
_dependency5.DeleteTemp();
_

メソッドは正しく呼び出されるべきではありませんか?これは、テストする必要があるケースです。

そして、それらの例外のロールバックアクションは何ですか?ロールバックアクションがある場合は、例外がスローされた場合にアクションが呼び出されるかどうかをテストする必要があります。

パラメータについては、ここではテストしないでください。 _dependency3.ExecuteScript()メソッドが正しいパラメータを返すかどうかをテストする必要があります。

0
Mehmet Sunkur

このメソッドには単体テストも使用できます。これは、依存関係をモックすることで実行できます。原則は次のとおりです。

定義済みの結果を使用して、依存関係のモックを作成します(通常、依存関係のインターフェースを実装することによって)。たとえば、IsScriptNeeded()に対して常にtrueを返す_dependency2_の実装を提供します。

次に、_dependency3_を監視して、それが呼び出されているか(呼び出されているはずです!)、dependency4.SetScriptResult(...)のパラメーターが結果と一致しているかどうかを確認します。

C#には、FakeItEasyやMoqのようなライブラリがあり、モックを簡単に作成できます。 xUnitとFakeItEasyを使用したコードスニペットの例:

_using System;
using FakeItEasy;
using Xunit;

public class MyTest
{
    [Fact]
    public void Test() 
    {
        // Create the mock
        var mock = A.Fake<IMyDependency>();
        A.CallTo(() => mock.DoSomething()).Returns(true);

        // Create the class to test
        var sut = new SystemUnderTest(mock);
        sut.DoSomethingElse();

        // Assert that mock.DoSomething() was called
        A.CallTo(() => mock.DoSomething()).MustHaveHappened();
    }
}
_
0
jlnostr