2017-05-22 17 views
1
public void Pay() 
    { 
     // some insert db code 
     // ... 

     // Call Bank api 
     BankApi api = new BankApi(); 
     int result = api.pay(); 
     if(result == 1) 
     { 
      //... 
     } 
     else 
     { 
      //... 
     } 
    } 

ユニットテストではapiに電話しません。内部コードを変更せずに支払方法を模擬する方法(例えば、new BankApi()コード)?Unti Test:メソッドの結果を模擬してください

+0

あなたがすべてで**あなたはそのコードを変更することはできません意味インナーcode'を変更せずに '言う**?だから、 'BankApi'を' IBankApi'のようなインターフェースで置き換えることはできませんでしたか? –

+5

疎結合でコードを書き直すことなくこれを行う方法はありません。 –

+2

TypeMockを使用してこれを行うことができます。できるならDIを使うようにコードを書き直すのが良いですが、もしそれが絶対にオプションでないなら、TypeMockがあなたを助けるかもしれません。捜しなさいsolate.Fake.AllInstances (); TypeMockを使用してから数年が経ちました。 – Stuart

答えて

2

まず、前述のように、インターフェイスを作成する必要があります。その後、何を行うことができますすることは(私はあなたがあなたのアプリケーションへの参照としてNuGetパッケージ「部品番号」を追加する必要があり、あなたでしょう、ここで「あなたのモック」部品番号を使用しています。このようなモックこのインタフェース

public interface IBankApi 
{ 
    int pay(); 
} 

ですその直後、あなたがこのAPI「擬似オブジェクト」、そして、

apiMock.Setup(x => x.pay()).Returns(1); // 

)それは実際あざけるだろう(この呼び出しが返すべきか教えてくれる、

apiMock = new Mock<IBankApi>(); 

)もちろん、他のモックライブラリをすることができます使用することができますを使用して使用するapiMock.Object

ここで私があなたに与えたこの情報は、あなたの問題を直接解決するものではありません。


コメントで述べたように、あなたはあなたのコードのよりよい脱共役を必要としています。

このような非結合を可能にするために、たとえば、ある種の「依存性注入」が必要です。

using Microsoft.VisualStudio.TestTools.UnitTesting; 
using Moq; 

[TestClass] 
public class TestMyMethod 
{ 
    [TestMethod] 
    public void MyMethod_WithBankApiReturns1_ShouldHaveThingsThatHappens() 
    { 
     // Arrange 
     var apiMock = new Mock<IBankApi>(); 
     apiMock.Setup(api => api.pay()) 
      .Returns(1); 

     var myObject = new ClassThatUsesYourBankApi(apiMock.Object); 

     // Act 
     int result = myObject.MethodThatUseTheApi(); 

     // Assert 
     // Here you test that the things that should have happened when the api returns 1 actually have happened. 
    } 
} 

ここを理解するために重要なもの、ということである:メソッドがあること

public class ClassThatUsesYourBankApi 
{ 
    private readonly IBankApi _api; 

    // the constructor will be given a reference to the interface 
    public ClassThatUsesYourBankApi (IBankApi api) 
    { 
     // here you could check for null parameter and throw exception as needed 
     this._api = api; 
    } 

    // this method can now be tested with the mock interface 
    public void MethodThatUseTheApi() 
    { 
     int result = this._api.pay(); 

     if (result == 1) 
     { 
      // some things that happens 
     } 
     else 
     { 
      // some other thing 
     } 
    } 
} 

どのようにユニットテスト:ここに

はそれを行うことができる方法の簡単な例です。あなたがテストしたいメソッドを模擬する必要があるAPIをインスタンス化してはいけません。

つまり、あなたのメソッドをあなたのapiと「切り離す」ことは、インターフェイスにプログラミングすることによって行われ、ユニットテストするメソッドには直接 var api = new BankApi() のコードがありません。

私はそれを行う方法を示し、他にもあります。

2

従来のコードを変更せずにBankApiクラスを模擬することができるので、具体的なクラスを模擬できる単体テストフレームワークが必要です。例えば Typemockを使用してメソッドのテスト:

[TestMethod] 
public void ExampleTest() 
{ 
    //fakes the next BankApi instace 
    var handler = Isolate.Fake.NextInstance<BankApi>(); 

    //change the pay method behavior 
    Isolate.WhenCalled(() => handler.pay()).WillReturn(1); 

    new ClassUnderTest().Pay(); 
} 
関連する問題