2

クラスを独自にインスタンス化する C# クラスがありますNetworkCommunicatorNetworkCommunicator単体テスト用にクラスをモック化し、それを非常に単純なスタブに置き換えたいと思います。

ただし、NetworkCommunicatorがパラメーターとして渡されることはありません。テスト対象のクラスによって作成されます。

Ruby では、これを簡単にモックアウトできます。Java では、これが依存性注入が必要な理由です。これは、このプロジェクトには重すぎます。Moqおそらくまたは同様のものを使用して、C#でこれをモックする簡単な方法はありますか?

4

5 に答える 5

5

DI はこのプロジェクトには重すぎるとおっしゃいましたが、トラック ドライバーの DI を試してみませんか?

public interface IDependency
{
    void DoSomeStuff();
}

public class ClassUnderTest
{
    private IDependency _dependency;

    public ClassUnderTest(IDependency dependency)
    {
        _dependency = dependency;
    }

    public ClassUnderTest() : this(new Dependency())
    {}

    public void ImportantStuff()
    {
        _dependency.DoSomeStuff();
    }
}

このコンストラクター チェーン手法を使用すると、DI や IoC を接続することを心配することなく、必要なだけ IDependency をモックできるようになりました。

于 2012-12-31T00:20:46.487 に答える
3

コードをリファクタリングして、依存関係を渡す必要があります。Visual Studio 2012 では、typemockを偽物に代わる使いやすいものとして使用することもできます。

于 2012-12-31T00:16:10.673 に答える
3

テスト対象のクラスから継承する「TestClass」を作成します。モック化されたインスタンスでそのパラメーターをオーバーライドする 新しいインスタンスを返すテスト対象のクラスにプロパティを作成する

public class ClassUnderTest {

public string MethodYouAreTesting(int someInput) {

var networkCommunicator = GetNetworkCommunicator();
// Do some stuff that I might want to test
return "foo";

}

public virtual NetworkCommunicator GetNetworkCommunicator {
    return new NetworkCommunicator();
}

}

[TestFixture]
public class ClassUnderTestTests {
public void GivenSomeCondition_MethodYouAreTesting_ReturnsFooString() {

var classToTest = new TestClassUnderTest();
var result = classToTest.MethodYouAreTesting(1);
Assert.That(result, Is.EqualTo("foo");

}
}

public class TestClassUnderTest : ClassUnderTest {

public override GetNetworkCommunicator {
return MockedNetworkCommunicator;
}

}

私はこのテクニックを「Art of Unit Testing」で読み、完全な DI へのリファクタリングが意味をなさない場合、またはテストしているクラスが変更できない場合に頻繁に使用します。

お役に立てれば。

于 2012-12-31T00:26:12.470 に答える
1

NetworkCommunicator クラスを独自にインスタンス化する C# クラスがあります。

お気づきのように、これは C# でこれをモックしたい場合のショー ストッパーです。解決策は簡単で、インスタンス化されたクラスのコンテキスト/目的によって異なります。

  • 再利用可能なコンポーネントの場合、依存関係として注入します
  • 需要が発生するたびに作成する必要がある場合は、ファクトリ経由で提供します

いずれにせよ、DI が必要になります(2 番目の例の factory も自然に注入されます)。

Java では、これが依存性注入が必要な理由です。これは、このプロジェクトには重すぎます。

依存性注入は重すぎますか? DI は設計パターンであり、必要のないときに使用すると重くなります。あなたの質問は、それが必要であることを明確に示しています。おそらく、DI コンテナーはプロジェクトにとって重すぎるということでしょうか? プロジェクトの複雑さに応じて、 DI を適用する適切な方法を選択する必要があるため、これは真実かもしれません。

Greg Smith の回答で提案されているようなソリューションを適用する際に注意すべき点をもう 1 つ挙げたいと思います。基本的に、API はコンストラクターで終わります。

public TestedClass() : this(new Dependency()) ...
public TestedClass(IDependency) ...

一見すると魅力的かもしれませんが、長期的な視点を考慮すると、いくつかの問題が浮かび上がり始めます。

  • 持っTestedClass ている必要があります IDependencyか、それがなくてもうまくいきますか?
  • デフォルト(パラメータなしのコンストラクタ) のデフォルト (適切に使用するには、実装の詳細レベルの知識が必要です)?
  • 密に結合されたコンポーネントを作成します(TestedClassアセンブリは、他のアセンブリを参照する必要がある可能性があります-Dependencyとにかく関係がない場合でも)

これは、 Bastard Injectionなど、さまざまな名前で使用されるアンチパターンです。もちろん、これらの問題の一部は軽減される可能性があります (コンストラクターを保護/内部にする、または同じアセンブリで既定の実装を行うなど) が、アンチパターンとその長期的な影響は残ります。また、通常の DI よりも単純でも、高速でも、コードが少ないわけでもありません。

適切な DI を適用するか、アンチパターンやサード パーティのフレームワーク (MS Fakes) を使用して回避するか、どれがそれほど重くないかを自問する必要があります。

于 2012-12-31T12:06:59.467 に答える
1

組み込みの Fakes システムがあり、http://msdn.microsoft.com/en-us/library/hh549175.aspx でよく説明されています

それがあなたのユースケースにとって重すぎる場合は、PrivateObjectクラスの方が便利かもしれません。

于 2012-12-31T00:20:25.883 に答える