6

「SUT内で何が起こるかを制御できるようにクラスをスタブする方法」に関する複数の回答を見てきました。

彼らは 1 つのことを言います:

インターフェースを作成し、依存性注入を使用してそのインターフェースを注入し、同じインターフェースを使用してスタブを作成し、それを SUT に注入します。

しかし、以前の職場で学んだこと:

単体テストを行う場合は、すべてのクラス/機能をテストします。

それは、特定の関数レイアウトを持つすべてのクラスに対して、インターフェイスを作成する必要があるということですか?

これは、クラス/ファイルの量が約 2 倍になることを意味します。

以下の例に見られるように、これは「進むべき道」ですか、それとも単体テスト プロセスで何か不足していますか?

注: 私は VS2012 Express を使用しています。つまり、「フェイカー」フレームワークはありません。「標準」の VS2012 単体テスト フレームワークを使用しています。

非常に単純な例として、SUT に渡された各インターフェイスをスタブ化できるようにします。

IFoo.cs

public interface IFoo
{
    string GetName();
}

Foo.cs

public class Foo : IFoo
{
    public string GetName()
    {
        return "logic goes here";
    }
}

IBar.cs:

public interface IBar : IFoo
{
    IFoo GetFoo();
}

Bar.cs:

public class Bar : IBar
{
    public string GetName()
    {
        return "logic goes here";
    }

    public IFoo GetFoo()
    {
        return null; // some instance of IFoo
    }
}

IBaz.cs:

public interface IBaz
{
    IBar GetBar();
}

Baz.cs:

public class Baz
{
    public IBar GetBar()
    {
        return null; // some instance of IBar
    }
}
4

5 に答える 5

6

私の意見では、単体テストのためだけにインターフェイスを作成するべきではありません。ツールを喜ばせるためにコードの抽象化を追加し始めた場合、それらは生産性の向上に役立ちません。作成するコードは、理想的には、特定のビジネス目的/ニーズに対応する必要があります。直接的または間接的に、コード ベースの保守または進化を容易にすることによって実現します。

インターフェースは時々これを行いますが、常にそうであるとは限りません。通常、コンポーネントにインターフェイスを提供することは良いことですが、内部クラス (つまり、型がパブリックに宣言されているかどうかに関係なく、特定のプロジェクト内でのみ使用されるコード) にはインターフェイスを使用しないようにしてください。これは、コンポーネント (特定の問題を解決するために連携する一連のクラスなど) がより大きな概念 (ロガーやスケジューラなど) を表しているためです。 .

解決策 (コメントの最初の Robert へのヒント) は、モッキング フレームワークを使用して、実行時に互換性のある置換型を生成することです。フレームワークをモックすると、テスト対象のクラスが置換されたダミーと正しく対話したことを確認できます。前述のように、Moq はおしゃれな選択です。Rhino.Mocks と NMock は、他の 2 つの人気のあるフレームワークです。Typemock Isolator はプロファイラーにフックされ、より強力なオプションの 1 つです (非仮想のプライベート メンバーを置き換えることもできます) が、商用ツールです。

単体テストをどこまで行うべきか、ルールを作るのはよくありません。何を開発しているか、何を目標としているかによって異なります。正確さが常に市場投入までの時間よりも優先され、コストが問題にならない場合は、すべてを単体テストすることをお勧めします。ほとんどの人はそれほど幸運ではなく、妥当なレベルのテスト カバレッジを達成するために妥協する必要があります。どのくらいテストする必要があるかは、チームの全体的なスキルレベル、予想される寿命、記述されているコードの再利用などによっても異なります。

于 2013-05-24T00:14:32.270 に答える
3

純粋主義者の観点からは正しい方法かもしれませんが、本当に重要なことは、外部の依存関係 (データベース、ネットワーク アクセスなど)、計算コストや時間がかかるもの、そうでないものを確認することです。完全に決定論的なものは抽象化されており、単体テストで簡単に置き換えることができます。

于 2013-05-23T23:45:11.057 に答える
0

私は仮想メソッドルートに行きます。テストする必要があるすべてのクラスのインターフェイスを作成することは、特にメソッドの定義を確認するたびに「実装に移動」するために Resharper のようなツールが必要な場合に、非常に負担になります。また、メソッド シグネチャが変更されたり、新しいプロパティやメソッドが追加されたりするたびに、両方のファイルを管理および変更するオーバーヘッドが発生します。

于 2015-06-23T22:39:58.357 に答える
0

テストの観点からは、コード内のすべてのクラスに対してインターフェイスを作成する必要はありません。インターフェースを作成して、抽象化レイヤーの背後にある外部依存関係の具体的な実行を隠します。したがって、直接 HTTP 接続を必要とするクラスをロジックに混在させるのではなく、接続コードをクラスに分離し、クラスのメンバーであるインターフェイスを実装し、そのインターフェイスの代わりにモックを挿入します。 . そうすれば、ロジックを独立して依存関係なくテストできます。「テストされていない」コードは、他の手段でテストできるボイラープレート HTTP 接続コードだけです。

于 2013-05-24T01:13:16.947 に答える