オンライン機能を備えた単体テストクラス


23

オンライン機能を必要とするプライベート機能を持つクラスの機能を単体テストするとき。それをどのようにテストしますか?

例えば:

public class Foo
{
    public int methodA()
    {
         int val = goOnlineToGetVal();

         return val;
    }

    private int goOnlineToGetVal()
    {
        CloudService c = new CloudService();
        int oval = c.getValueFromService();
        return oval;
    }
}

機能をテストする場合、「methodA()」は「goOnlineToGetVal()」を使用しようとしますが、このテストが機能なしで実行された場合、オンラインに移行しようとします。オンラインに接続せずに、どのように100%のクラスをカバーしますか


メソッドはクラウドAPIを呼び出すだけですか、それとも追加の作業を行いますか?
ウィンストン


4
依存性注入?
PhaDaPhunk

回答:


76

new CloudService()

そして、あなたの問題があります。

最新のオブジェクト指向設計では、この種の依存関係を直接構築するのはなく渡すことを推奨しています。これは、関数自体に渡すことも、構築時にクラスに渡すこともできます。そのような複雑さが必要な場合は、Inversion of Controlコンテナーによって取得または集約することもできます。

その時点で、テスト中に「オンライン」データを提供するために、模擬/偽のサービスを渡すのはかなり簡単になります。さらに良いことに、ソフトウェアが十分に柔軟であるため、一部の(政府?)クライアントが来て、その価値のためにクラウドを使用したくない場合に迅速に適応できます。または、あるクラウドプロバイダーを別のクラウドプロバイダーにダンプします。または...


7
私はちょうど依存性注入が何であるかを理解するのにかなり近づいたと思います。
マルツェルム14

アプリケーションに必要なすべてのインスタンスを作成するのに最適な場所はどこですか?できるだけアプリケーションの上部に近いですか?これまでのところ、依存性注入のみを適用できます。ある時点で、インスタンスを引数として渡すのではなく、自分でインスタンスを作成する必要があります。
ポール14

3
@ポール-それは依存します。私の経験では、アプリケーションは非常に頻繁にバイナリツリーのように見えます。1つのクラス/関数/モジュールが2つを結合して、より複雑な動作を提供します。これらの「接着剤」クラスの1つは、具体的な実装を指定するクラスです。これは、上記の何かが他の何かと接着するために使用されます。首尾一貫して。「最良の」場所とは、コードに実行させるべきではないことを行わせたり、知らせたりすることなく、必要なことを実行させる場所です。それは異なります。
テラスティン14

2
@Paul通常、アプリケーションは、直接テストされ、この種の依存性注入を使用する「ライブラリ」と、アプリケーション固有のコードに分けられます。後者は通常、ユーザー提供のデータでライブラリを直接呼び出すGUI、Webサービス、またはコマンドラインインターフェイスに要約されます。基本的に、アプリケーション固有のコードは、依存関係が注入されたライブラリが期待する具体的な実装を作成します。
ダークホッグ14

@Paul Castle Windsor、StructureMap、Ninject、UnityなどのIoCコンテナーをご覧ください。トップダウンから、彼らは決して依存性の注入を行うための唯一の方法ですが、彼らは、オブジェクトグラフの構築についての考え方の面で非常に有益なことができ
ベン・アーロンソン

37

私はこのように実装します:

public class Foo
{
    private ICloudService cloudService;

    public Foo(ICloudService s)
    {
       cloudService=s;
    }

    public int methodA()
    {
         int val = goOnlineToGetVal();

         return val;
    }

    private int goOnlineToGetVal()
    {
        int oval = cloudService.getValueFromService();
        return oval;
    }
}

インターフェイスICloudServiceは、テスト用のモックまたは「実際の」クラウドサービスのいずれかで実装できます。インスタンス化new CloudService()がのすべての呼び出しに必須である場合getValueFromService、またはCloudService変更できないサードパーティAPIからのICloudServiceものである場合は、適切な呼び出しから派生して適切な呼び出しを行うラッパーを実装します。


1
これは間違いなく進むべき方法です。インターフェイスをモックして、テストを完全に制御できるクラスライブラリがあります。
グレッグブルクハート14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.