2016-12-16 4 views
3

の残りの部分へのアクセスを持たずに、私はクラスPersonとインターフェースがあります。しかし、私は「ドン、書き方C#のNUnitのテストコード

interface IService 
{ 
    double GetAccDetails(int personId); 
} 

public class Person 
{ 
    private int _personId; 
    private IService _service; 

    public Person(int personId, IService service) 
    { 
     _personId= personId; 
     _service = service; 
    } 

    public double Amount {get; set;} 

    public void UpdateBackingAcc() 
    { 
     Amount = _service.GetAccDetails(_personId); 
    } 
} 

をそして私はNUnitのテストとコードのこの部分をカバーするために持っていますサービスにアクセスできますが、公開したコードにのみアクセスできます。

だから私の質問は以下のとおりです。

  1. 私はユニットテストを書くためにそれをmoqueべきでしょうか?はいの場合、それは常に私に静的な価値を返すので、私はそれの利益があまり見えません。

  2. 指定されたインターフェイスに対してどのようなテストを作成できますか?私は、テストの1つがpersonId1を使用して静的な値を取得しようとする可能性があると仮定し、personId2を使用して、別の値を取得し、その量が更新されたかどうかを確認します。そうだとすれば、これは単体テストでしかないかもしれません。

おそらくそれは値が負であるかどうかをチェックすることは理にかなって...多分も値が0 ...

ある他の任意のアイデア?

答えて

2

クラスPersonには、publicコンストラクタpublic get \ setプロパティとpublicメソッドがあります。クラスのパブリックインターフェイスをテストすることをお勧めします。あなたはクラスをテストすることができます:

  1. Ctor、あなたはNULLに対してIServiceを検証する必要があります。それをテストするコードを改善してください。
  2. あなたはあなたの財産の取得をテストし、UpdateBackingAccIServiceが呼び出され、値がAmountプロパティ内に保存されることが呼び出されたときに、あなたは確認することができます
  3. を設定することができます。
1

は限り、あなたは、サードパーティのサービスと対話しているので、行くので、それを制御することはできませんユニットテストを書くなど、モックはあなたの最良の選択肢です。

私は個人的に、そのサービスとのやりとりを制御できるラッパークラスをサービスの周りに書くことをお勧めします。

私は1つのテストで大丈夫でしょう:嘲笑されたサービスから返された値がAmountに割り当てられていることをテストします。これらのすべてのケースが同じコードパスを通過するので、数値がゼロ、正または負であるかどうかは関係ありません。

インテグレーションテストを実際にサービスとやり取りして、実際にサービスと通信して値を取得していることをテストすることができます。

1

1 /はいサービスはテストされたクラスの外部依存であり、それは嘲笑されるべきです。

2 /インターフェイスはコードがないためテストできません。 Personクラスをテストできます。

私はあなたに同意します。ここでconstructorをテストし、フィールドが正しく設定されていることを証明できます。しかし、合理的なテストは私のことができることは、次のテストになります。 Amountには、UpdateBackingAccメソッドが実行された後にサービスから返された値が含まれていることがテストされます。

[TestMethod] 
public void UpdateBackingAcc_WhenCalled_AmountContainsValueReturnedFromService() 
{ 
    Mock<IService> serviceMock = new Mock<IService>(); 
    const double expectedResult = 100; 
    const int personId = 200; 
    serviceMock.Setup(s => s.GetAccDetails(It.Is<int>(id => id == personId))) 
     .Returns(() => expectedResult); 
    Person person = new Person(personId, serviceMock.Object); 

    // Act 
    person.UpdateBackingAcc(); 

    // Assert 
    double actualResult = person.Amount; 
    Assert.AreEqual(expectedResult, actualResult); 
} 

ここでは、サービスに関するすべての情報がありません。例えば。無効なpersonIdで呼び出されると、サービスは何を返しますか?これを考慮すると、さらにいくつかのテストを書くことができる。

  • UpdateBackingAcc_PersoneIdValid_AmountContainsValueReturnedFromService
  • UpdateBackingAcc_PersoneIdInvalid_ThrowsException

[TestMethod] 
[ExpectedException(typeof(InvalidOperationException))] 
public void UpdateBackingAcc_PersoneIdInvalid_ThrowsException() 
{ 
    // Arrange 
    Mock<IService> serviceMock = new Mock<IService>(); 
    const int invalidPersonId = -1; 
    serviceMock.Setup(s => s.GetAccDetails(It.Is<int>(i => i == invalidPersonId))) 
     .Throws<InvalidOperationException>(); 
    Person person = new Person(invalidPersonId, serviceMock.Object); 

    // Act 
    person.UpdateBackingAcc(); 

    // Assert 
    // Throws exception 
} 
+0

私は 'がexception'は' Person'クラスの責任ではありません例外だと思います。 – Fabio

+0

@Fabioあなたは絶対に正しいです!理論的には、サービスが無効なIdを受け取り、例外をスローする可能性を考えようとしていました。編集された回答をご覧ください。 – dee

+0

いいえ@dee、私の要点は 'try .. catch'はまったく必要ないということでした。もちろん、テストする必要はありません。サービスがスローされる場合は投げてください。 – Fabio

関連する問題