It.IsAny / It.Is
これらは、テスト対象のコード内で新しい参照型を渡すときに役立ちます。たとえば、次のようなメソッドがあるとします。
public void CreatePerson(string name, int age) {
Person person = new Person(name, age);
_personRepository.Add(person);
}
リポジトリで add メソッドが呼び出されたことを確認したい場合があります。
[Test]
public void Create_Person_Calls_Add_On_Repository () {
Mock<IPersonRepository> mockRepository = new Mock<IPersonRepository>();
PersonManager manager = new PersonManager(mockRepository.Object);
manager.CreatePerson("Bob", 12);
mockRepository.Verify(p => p.Add(It.IsAny<Person>()));
}
このテストをより明確にしたい場合は、人物オブジェクトが一致しなければならない述語を提供することで It.Is を使用できます。
[Test]
public void Create_Person_Calls_Add_On_Repository () {
Mock<IPersonRepository> mockRepository = new Mock<IPersonRepository>();
PersonManager manager = new PersonManager(mockRepository.Object);
manager.CreatePerson("Bob", 12);
mockRepository.Verify(pr => pr.Add(It.Is<Person>(p => p.Age == 12)));
}
このようにして、 add メソッドを呼び出すために使用された person オブジェクトの age プロパティが に設定されていない場合、テストは例外を通過します12
。
タイムズ
次のような方法がある場合:-
public void PayPensionContribution(Person person) {
if (person.Age > 65 || person.Age < 18) return;
//Do some complex logic
_pensionService.Pay(500M);
}
テストしたいことの 1 つは、65 歳以上の人がメソッドに渡されたときに、pay メソッドが呼び出されないことです。
[Test]
public void Someone_over_65_does_not_pay_a_pension_contribution() {
Mock<IPensionService> mockPensionService = new Mock<IPensionService>();
Person p = new Person("test", 66);
PensionCalculator calc = new PensionCalculator(mockPensionService.Object);
calc.PayPensionContribution(p);
mockPensionService.Verify(ps => ps.Pay(It.IsAny<decimal>()), Times.Never());
}
同様に、コレクションを繰り返し処理し、コレクション内の各アイテムのメソッドを呼び出す状況を想像することができます。特定の回数だけ呼び出されていることを確認したい場合と、そうでない場合があります。お手入れ。
SetupGet / SetupSet
これらの人について注意する必要があるのは、モックの設定方法ではなく、コードがモックと対話する方法を反映していることです。
public static void SetAuditProperties(IAuditable auditable) {
auditable.ModifiedBy = Thread.CurrentPrincipal.Identity.Name;
}
この場合、コードは IAuditable インスタンスの ModifiedBy プロパティを設定し、IPrincipal の現在のインスタンスの Name プロパティを取得しています。
[Test]
public void Accesses_Name_Of_Current_Principal_When_Setting_ModifiedBy() {
Mock<IPrincipal> mockPrincipal = new Mock<IPrincipal>();
Mock<IAuditable> mockAuditable = new Mock<IAuditable>();
mockPrincipal.SetupGet(p => p.Identity.Name).Returns("test");
Thread.CurrentPrincipal = mockPrincipal.Object;
AuditManager.SetAuditProperties(mockAuditable.Object);
mockPrincipal.VerifyGet(p => p.Identity.Name);
mockAuditable.VerifySet(a => a.ModifiedBy = "test");
}
この場合、IPrincipal のモックに name プロパティを設定しているため、プロパティ自体を設定していない Identity の Name プロパティで getter が呼び出されたときに "test" が返されます。
SetupProperty / SetupAllProperties
上記のテストを読むように変更された場合を見てください
[Test]
public void Accesses_Name_Of_Current_Principal_When_Setting_ModifiedBy() {
Mock<IPrincipal> mockPrincipal = new Mock<IPrincipal>();
Mock<IAuditable> mockAuditable = new Mock<IAuditable>();
mockPrincipal.SetupGet(p => p.Identity.Name).Returns("test");
var auditable = mockAuditable.Object;
Thread.CurrentPrincipal = mockPrincipal.Object;
AuditManager.SetAuditProperties(auditable);
Assert.AreEqual("test", auditable.ModifiedBy);
}
テストは失敗します。これは、指定しない限り、Moq によって作成されたプロキシがプロパティの set メソッドで実際に何もしないためです。実際、モック オブジェクトは次のようになります。
public class AuditableMock : IAuditable {
public string ModifiedBy { get { return null; } set { } }
}
テストに合格するには、Moq にプロパティを設定して標準のプロパティ動作を持たせる必要があります。SetupProperty を呼び出すことでこれを行うことができ、モックは次のようになります。
public class AuditableMock : IAuditable {
public string ModifiedBy { get; set; }
}
上記のテストは、値「test」がモックに対して保存されるため、合格します。複雑なオブジェクトをモックする場合、すべてのプロパティに対してこれを実行したい場合があるため、 SetupAllProperties ショートカット
最後に、IDE の電球は ReSharper プラグインです。