2017-05-19 11 views
1

私はリポジトリ(EFでデータアクセス層)を呼び出すマネージャ(ビジネス層)を持っています。 マネージャのロジックは、2つの異なるラムダ式をパラメータとして持つリポジトリのメソッドを2回呼び出します。ラムダ式が異なるメソッドを2回モックする方法は?

私の質問は、最初のラムダに対して与えられた応答を返すように私のリポジトリをモックする方法ですが、2番目のラムダに対しては別の応答を返しますか?例えば

public class Person 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

public class Relation 
{ 
    public int GiverId { get; set; } 
    public int ReceiverId { get; set; } 
} 

public interface IRelationRepository 
{ 
    bool Loves(Expression<Func<Relation, bool>> predicate); 
} 

public class RelationRepository : IRelationRepository 
{ 
    public bool Loves(Expression<Func<Relation, bool>> predicate) 
    { 
     // Some logic... 
     return true; 
    } 
} 

public class KissManager 
{ 
    private readonly IRelationRepository repository; 

    public KissManager(IRelationRepository repository) 
    { 
     this.repository = repository; 
    } 

    public bool Kiss(Person p1, Person p2) 
    { 
     var result = this.repository.Loves(r => r.GiverId == p1.Id && r.ReceiverId == p2.Id) 
      && this.repository.Loves(r => r.GiverId == p2.Id && r.ReceiverId == p1.Id); 
     return result; 
    } 
} 

[TestMethod] 
public void KissWithReceiverNotInLove() 
{ 
    // Arange. 
    var p1 = new Person { Id = 5, Name = "M. Love" }; 
    var p2 = new Person { Id = 17, Name = "Paul Atreid" }; 

    var kissRepositoryMock = new Mock<IRelationRepository>(); 
    kissRepositoryMock 
     .Setup(m => m.Loves(r => r.GiverId == p1.Id && r.ReceiverId == p2.Id)) 
     .Returns(true); 
    kissRepositoryMock 
     .Setup(m => m.Loves(r => r.GiverId == p2.Id && r.ReceiverId == p1.Id)) 
     .Returns(false); 

    var kissManager = new KissManager(kissRepositoryMock.Object); 

    // Act. 
    var result = kissManager.Kiss(p1, p2); 

    // Assert. 
    Assert.IsFalse(result); 
} 
+1

[SetupSequence(https://codecontracts.info/2011/07/28/moq-setupsequence-is-great-for-mocking/)。あなたが正しい順序でそれらを設定していることを確認してください。 –

+0

ありがとう、それは動作します! しかし、私は(マネージャーで)私の呼び出しの順序を変更すると機能的に何も変わらないが、私のテストは失敗する。あなたは別の方法を知っていますか? – C0b0ll

+1

SetupSequenceの順序は、SUT内のものと一致する必要があります。 SUTで通話の順序を変更すると、テストを更新する必要があります。この点でテストは脆弱です。 –

答えて

2

1つのオプションは、方法It.IsAny<Expression<Func<Relation, bool>>>()を介して任意の式/述語を受け入れて所定の述語/発現に所望の動作を可能にする偽のデータ・ソースを使用するようにセットアップすることです。

[TestMethod] 
public void _KissWithReceiverNotInLove() { 
    // Arange. 
    var p1 = new Person { Id = 5, Name = "M. Love" }; 
    var p2 = new Person { Id = 17, Name = "Paul Atreid" }; 
    var relations = new List<Relation>() 
    { 
     new Relation{ GiverId = p1.Id, ReceiverId = p2.Id } 
     //The above should satisfy the first expected predicate. 
     //Note there are no other relations in this list. 
     //That is by design to make the second predicate return false. 
    }; 

    var kissRepositoryMock = new Mock<IRelationRepository>(); 

    kissRepositoryMock 
     .Setup(m => m.Loves(It.IsAny<Expression<Func<Relation, bool>>>())) 
     .Returns((Expression<Func<Relation, bool>> predicate) => relations.Any(predicate.Compile())); 

    var kissManager = new KissManager(kissRepositoryMock.Object); 

    // Act. 
    var result = kissManager.Kiss(p1, p2); 

    // Assert. 
    Assert.IsFalse(result); 
} 
+0

これはリポジトリのデータセットをシミュレートする非常に良い方法です。ご回答有難うございます ! – C0b0ll

2

それが最初の記事のコメントで述べているとおり、SetupSequenceを使用することも可能であるが、それは実装に依存していないので、私は@Nkosiソリューションを好みます。

この例では、SetupSequenceの使用例を掲載します。それは誰かにとって役に立ちます。代わり `Setup`の

[TestMethod] 
public void KissWithReceiverNotInLove() 
{ 
    // Arange. 
    var p1 = new Person { Id = 5, Name = "M. Love" }; 
    var p2 = new Person { Id = 17, Name = "Paul Atreid" }; 

    var kissRepositoryMock = new Mock<IRelationRepository>(); 
    kissRepositoryMock 
     .SetupSequence(m => m.Loves(It.IsAny<Expression<Func<Relation, bool>>>())) 
     .Returns(true) 
     .Returns(false); 

    var kissManager = new KissManager(kissRepositoryMock.Object); 

    // Act. 
    var result = kissManager.Kiss(p1, p2); 

    // Assert. 
    Assert.IsFalse(result); 
} 
関連する問題