18

using ステートメントを持つメソッドの単体テストを作成するにはどうすればよいですか?

たとえば、 method があるとしFooます。

public bool Foo()
{
    using (IMyDisposableClass client = new MyDisposableClass())
    {
        return client.SomeOtherMethod();
    }
}

上記のコードのようなものをテストするにはどうすればよいですか?

usingステートメントとDispose()オブジェクトを手動で使用しないことを選択することがあります。誰かが私に使えるトリックを教えてくれることを願っています。

4

8 に答える 8

22

IMyDisposableClassnew キーワードを使用するのではなく、(親クラスに注入された) ファクトリを使用してを構築する場合は、をモックIMyDisposableして、dispose メソッド呼び出しで検証を行うことができます。

public bool Foo()
{
    using (IMyDisposableClass client = _myDisposableClassFactory.Create())
    {
        return client.SomeOtherMethod();
    }
}
于 2009-12-23T16:08:17.907 に答える
18

すでにコードがあり、それをテストする方法を尋ねている場合は、最初にテストを書いていないので、実際には TDD を行っていません。

ただし、ここにあるのは依存関係です。したがって、TDD アプローチはDependency Injectionを使用することになります。これは、 UnityのようなIoCコンテナーを使用して簡単に行うことができます。

TDD を「適切に」実行する場合、この種のシナリオでは、思考プロセスは次のように実行する必要があります。

  • 私はする必要がありますFoo
  • このために、(新規または既存の)インターフェースを実装する外部依存関係に依存しますIMyDisposableClass
  • したがって、コンストラクターを介して宣言さIMyDisposableClassれているクラスにを挿入しますFoo

次に、失敗する 1 つ (または複数) のテストを記述し、関数本体を記述している時点でのみ、ブロックFooを使用する必要があるかどうかを判断します。using

実際には、はい、usingブロックを使用することをよく知っているかもしれません。しかし、TDD の要点の 1 つは、これを必要とするオブジェクトを使用する必要があることを (テストによって) 証明するまで、それについて心配する必要がないということです。

ブロックを使用する必要があると判断したらusing、失敗するテストを作成します。たとえば、Rhino MocksDisposeなどを使用して、実装するモック オブジェクトで呼び出される期待値を設定しますIMyDisposableClass

例 (Rhino Mocks を使用して mock IMyDisposableClass)。

[TestFixture]
public class When_calling_Foo
{
    [Test]
    public void Should_call_Dispose()
    {
        IMyDisposableClass disposable = MockRepository
                                        .GenerateMock<IMyDisposableClass>();

        Stuff stuff = new Stuff(disposable);

        stuff.Foo();

        disposable.AssertWasCalled(x => x.Dispose());
    }
}

IMyDisposableClass依存関係として注入されたFoo 関数が存在するクラス:

public class Stuff
{
    private readonly IMyDisposableClass _client;

    public Stuff(IMyDisposableClass client)
    {
        _client = client;
    }

    public bool Foo()
    {
        using (_client)
        {
            return _client.SomeOtherMethod();
        }
    }
}

そしてインターフェースIMyDisposableClass

public interface IMyDisposableClass : IDisposable
{
    bool SomeOtherMethod();
}
于 2009-12-23T16:17:07.900 に答える
6

あなたの質問は意味がありません。TDD を使用している場合は、作成した内容のテストが既にあるはずです。要件、テスト、設計、開発の順です。コードがテストに合格するか、合格しないかのどちらかです。

さて、あなたの質問が上記のコードを単体テストする方法である場合、それは完全に別の質問であり、他のポスターがそこに答えていると思います.

ときどき、開発者よりも流行語の方が多いと思います :)

于 2009-12-23T16:20:51.357 に答える
2

関連する事前条件または事後条件を指定できないため、そのようなラッパー メソッドは単体テスト可能ではありません。

IMyDisposableClassメソッドをテスト可能にするには、インスタンスをメソッドまたはクラス ホスティングに渡すFoo(そしてホスト クラス自体を実装するIDisposable) 必要があるため、本物の代わりにテスト ダブルを使用して、それとの相互作用を検証できます。 .

于 2009-12-23T16:09:09.747 に答える
0

あなたの質問は意味がありません。TDD を行っている場合、投稿したメソッドはすでに完全にテストされています。そうでなければ、そもそも存在すらできませんでした。したがって、あなたの質問は意味がありません。

一方、投稿したメソッドが既に存在するが、完全にテストされていない場合は、とにかく TDD を行っているわけではなく、TDD に関する質問も意味がありません。

TDD では、テストされていないコードが存在することはまったくありません。限目。

于 2009-12-23T17:07:59.570 に答える
-1

Foo の仕様がなければ、それをテストする方法をどのように言えますか?

  1. Foo の仕様を取得します。
  2. すべての仕様と要件を満たしていることを確認するテストを作成します (または、合理的なサブセット - 一部の機能では、テストに事実上無限の量のデータが必要になる場合があります)。

そこに 2 番目の暗黙の質問があると思います。これは、MyDisposableClass の使用を正しくテストする方法です。using 句を終了することによってオブジェクトが解放されたときにオブジェクトを破棄します。これは別のテストの問題であり、Foo の仕様は MyDisposabeClass の使用などの実装固有の詳細を参照するべきではないため、Foo のテストと組み合わせるべきではありません。

他の投稿者がこの質問に答えていると思うので、これ以上詳しく説明しません。

于 2009-12-24T02:46:05.963 に答える
-1

Foo をテストしている場合は、内部で使用しているクラスの破棄を気にせずに、Foo の出力を確認する必要があります。

dispose メソッドをテストMyDisposableClassして、それが機能しているかどうかを確認したい場合は、それに対して個別の単体テストを作成する必要がありますMyDisposableClass

using { }ブロックは言語の一部であるため、ブロックを単体テストする必要はありません。動作していることを信頼するか、C# を使用しないかのどちらかです。Dispose():)それが呼び出されていることを確認するために単体テストを書く必要はないと思います。

于 2009-12-23T16:11:35.013 に答える