2017-05-19 12 views
1

저는 저장소 (EF가있는 데이터 액세스 레이어)를 호출하는 관리자 (비즈니스 계층)가 있습니다. 관리자의 논리는 두 개의 서로 다른 람다 식을 매개 변수로 사용하여 저장소의 메서드를 두 번 호출합니다.다른 λ 식으로 두 번 방법을 조롱 했습니까?

제 질문은 제 람다에 대해 주어진 응답을 반환하도록 제 저장소를 조롱하는 방법이지만 두 번째 람다에 대한 또 다른 응답을 반환합니까? 예를 들어

:

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/) 대신 Setup'의'. 올바른 순서로 설정했는지 확인하십시오. –

+0

고마워, 작동 해! 그러나 관리자의 통화 순서를 변경하면 아무 기능도 변경되지 않지만 내 테스트는 실패합니다. 다른 방법을 알고 있습니까? – C0b0ll

+1

SetupSequence의 순서는 SUT에있는 것과 일치해야합니다. SUT에서 통화 순서를 변경하면 테스트를 업데이트해야합니다. 테스트는이 점에서 취약합니다. –

답변

2

하나의 옵션이 설정에 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 사용 예를 게시합니다. 그것은 누군가에게 유용 할 수 있습니다.

[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); 
}