2016-08-19 2 views
0

サードパーティのSDKで定義されているクラスとインターフェイスを(Moqを使用して)モックしようとしています。 「具体的なクラスを模擬するときにプロパティを設定する方法

var mockVehicle = new Mock<IVehicule>(MockBehavior.Strict); 
mockVehicle 
    .SetupGet(v => v.Type) 
    .Returns("My custom vehicle"); 

が、私はJeepクラスに固有のユニットテストを記述する必要があり、私ができる:

public interface IVehicle 
{ 
    string Type { get; } 
} 
public class Vehicle 
{ 
    public string Type { get; } 
} 
public class Jeep : Vehicle, IVehicle 
{ 
} 

私は簡単そうのようなインターフェースを模擬することができます:ここでは、彼らがどのように見えるかの簡単な例を示しますそれを模倣する方法を理解していない。

私の最初の試み:

var mockJeep = new Mock<Jeep>(MockBehavior.Strict);

は、次のエラーをもたらした:私はセットアップType性質を持っていないので、

Moq.MockException: IVehicle.Type invocation failed with mock behavior Strict. 
All invocations on the mock must have a corresponding setup. 

に理解しています。

私の第二の試み:

System.NotSupportedException: Invalid setup on a non-virtual (overridable in VB) member: v => v.Type 

VehicleクラスのTypeプロパティは仮想ではないためにも理解しやすいです:

var mockJeep = new Mock<Jeep>(MockBehavior.Strict); 
mockJeep 
    .SetupGet(v => v.Type) 
    .Returns("Jeep"); 

は、次のエラーメッセージが得られました。

私の質問は:Jeepクラスを嘲笑するときにTypeプロパティを設定する方法はありますか?

+1

することができますようになります。少なくともmoqを使用しないで、具体的なクラスを模倣しないでください。第二に、あなたはそれをテストするために 'Jeep'クラスを模擬する必要はありません。モックを作成するとは、* fake *オブジェクトの一種を作成することを意味します。 – meJustAndrew

+0

この場合Moqができるのは、 'Jeep'の派生クラスとしてプロキシを作成することですが、' Type'プロパティをオーバーライドすることはできません。 Microsoft Fakesは、Visual Studioのライセンスレベルがあれば、Moqとうまく対戦します。他の解決策もありますが、私が考えることができるのは、ユニットテストでMoqを完全に置き換えるのではなく、完全に置き換えることです。私はこれを答えとして書き直します。 – RavB

+0

@RavB:ヒントのおかげで、私はMicrosoft Fakesで自分自身を教育します – desautelsj

答えて

2

moqは、Jeepの派生クラスとしてプロキシを作成しますが、非仮想Typeプロパティをオーバーライドすることはできません。 Moqを使ってMockを作成しようとすると、フレームワークはターゲットインタフェースを実装するか、ターゲットクラスから派生するクラスを生成することに注意してください。

Microsoft Fakesにアクセスするには、Visual Studioのライセンスレベルが必要です。

1

これはかなり一般的な質問ですので、私は別のアプローチを提案します。あなたがコントロールしていないクラスやインターフェイスを偽装/偽装/スタブするのは一般的に難しい作業です。さらに、これは通常、モックインスタンス内の他の人の機能を複製することにつながります。

より良い方法は、外部ライブラリとのやりとりを、インターフェイスと実装を制御するラッピングクラスに分離することです。これにより、インターフェイスのコンシューマをテストするためのインターフェイスを簡単に模擬/偽/スタブしてインターフェイスにすることができます。

これは、依然として分離レイヤークラスで何をすべきかという問題を残しています。このためには、実際にラッピングクラスと外部クラスの両方を実行する統合テストをさらに行う必要があります。次に、クラスとラッピングする外部クラスの組み合わせから期待される動作が得られることを確認します。

0

短い答えはいいえ、あなたはMoqを使って非仮想メンバーをモックできません。

しかし、私は何かを模倣する理由はないと思うが、モックする行動はないからだ。あなたが持っている唯一のメンバーは単純なstringです。たとえ可能であったとしても、おそらくそうではありません。あなたがJeepクラスをテストしようとしている場合

  • 、ちょうどそのメンバーのいずれかをからかっせずに直接 それをテスト。あなたは、そのメソッドをテストするために、依存関係として別の方法にJeep クラスを渡している場合はテスト対象システム(SUT)
  • の依存関係の1つの動作を制御する必要がある場合にモックにのみ使用してください new up Jeepインスタンスを作成し、この場合はテストで渡すことができます。 には境界交差動作(ネットワークコールなど)がありませんから、 はそれを擬似する必要はありません。述べたように、明らかな必要はありませんが、あなたはまた、(ケースモックがテーブルの上に戻っている、それは第二ケースだ場合、あなたの代わりにJeepIVehicleを渡すことができるはずであることを考えるかもしれません

ちなみに、あなたの階層はちょっと見えません。なぜVehicle自体がIVehicleを実装していませんか?

すなわち

public interface IVehicle 
{ 
    string Type { get; } 
} 
public class Vehicle: IVehicle 
{ 
    public string Type { get; } 
} 
public class Jeep : Vehicle 
{ 
} 

そしてJeepは既に車両とIVehicle両方であろう:)

+0

これは* my *階層ではないことを覚えておいてください。私はそれが少し外見には同意しますが、残念ながら私はそれを変更することはできません。第二に、私は本当にジープを依存関係として渡しているからです。それは私がそれを嘲笑しようとしている理由です。 – desautelsj

+0

十分に公正ですが、ジープは本当に境界を横切る実際の行動を本当に持っていますか?なぜあなたはその行動を模倣する必要がありますか? –

0

免責事項:私はTypemockで働きます。

Typemock Isolatorを使用することにより、非仮想メソッドを模擬することができます、あなたは偽物Jeep、その後のインスタンスは彼のメソッドの動作を変更することができ、この具体例では、そうするためには、あなたのコードを変更する必要はありません。 ここ
Jeepの模擬試験のための一例である:

[TestMethod] 
public void CallFakeJeepType_WillReturnWantedString() 
{ 
    var jeep = Isolate.Fake.Instance<Jeep>(); 
    Isolate.WhenCalled(() => jeep.Type).WillReturn("fake jeep"); 

    var result = Jeep.DoSomthing(jeep); 

    Assert.AreEqual("fake jeep", result); 
} 

注:Jeep.Typeが同様にセッターを持っていた場合は、使用することができtypemockのTrue propertyとテストはこの

var jeep = Isolate.Fake.Instance<Jeep>(); 
    jeep.Type = "fake jeep"; 
関連する問題