2014-05-23 2 views
2

SplitList 및 Update 메소드가있는 클래스가 제공됩니다. SplitList에서 업데이트가 호출되고 있습니다.moq를 사용하여 다른 메소드를 조롱하여 메소드가 호출되는지 테스트합니다.

class BaseClass 
{ 
    public void SplitList(ref IList<Type> objList) 
    { 
     IList<Type> SplitA = objList.Where(c=>c.currency == "USD").ToList(); 
     IList<Type> SplitB = objList.Where(c=>c.currency == "GBR").ToList(); 

     if(SplitA.Count() > 0) 
     { 
      Update(ref SplitA); 
     } 

     if(SplitB.Count() > 0) 
     { 
      Update(ref SplitB); 
     } 
    } 
} 

내가 테스트하고 싶은 것은 SplitList 메서드를 호출 할 때 업데이트가 호출되는 횟수입니다. 호출되는 경우 둘 다 또는 하나, 또는 없음을 의미합니다. 해당 메서드의 경계 조건을 테스트해야합니다.

그것이를 위해 내가이 진행 얼마나

,이 코드는 모의에 예상 호출 정확히 1 번으로 나에게 오류를 제공하지만했다됩니다

class TestClass 
{ 
    [TestMethod] 
    void TestSplitList() 
    { 
     Mock<BaseClass> mock = new Mock<BaseClass>(); 
     mock.Setup(m=>m.Update(ref List)).Verifiable(); 
     mock.Object.SplitList(ref List); 
     mock.Verify(m=>m.Update(ref List), Times.Exactly(1)); 
    } 
} 

0 번 : m => m.Update (.List)

아무도 도와 줄 수 있습니까?

+0

이 우리에게 업데이트 메소드 구현 –

+0

public 가상 업데이트보기 (IList의 updateList) { \t INT 카운트 = 0; \t foreach (updateList에 형식 objType) \t { \t \t objType.OrderNo = count ++; \t} \t return updateList; } 이와 비슷한 것입니다. – Anshul

답변

1

귀하의 SplitList 방법은 virtual입니까? (게시 된 코드는 코드베이스와 동일하지 않을 수 있습니다.)이 경우 Moq이이를 무시하고 Update이 호출되지 않습니다. 당신이 아닌 가상 만들 수 있습니다, 또는 MOQ이 라인을 추가하여 전화 한 : 당신이 조심,이 방법을 선택하면

mock.CallBase = true; 

을 그 모든 방법 것 "CallBase"(더 기대 구성원을 무시하지 않는 경우) .

업데이트 : SplitList 구현의 Update 메서드에 다른 목록을 전달 중입니다. 매개 변수가 objList 인 경우 다른 목록 (SplitASplitB)을 만들고이를 Update 방법으로 전달하십시오. SplitA (또는 SplitB) !=objList부터 테스트가 실패합니다.

여기에 ref을 사용해야합니까? 제거하면 코드가 더 간단 해지고 테스트가 통과됩니다. 목록은 여전히 ​​심판없이 달라질 것입니다. 미안합니다. 더 나은 테스트를 위해 논리를 변경해야 할 수도 있습니다.

+0

예 SplitList 메서드가 가상입니다. 하지만 CallBase를 추가하려고했습니다. 여전히 같은 오류가 발생하고 있습니다. 내가 생각하기에, 내가 mock 객체에 의해 실제 메소드를 호출 할 때, 내부 메소드에 호출하지 않는다고 생각한다. – Anshul

+0

@ user3667853 예, "Moq이이를 무시합니다"라는 말입니다. CallBase가 해결했지만 다른 문제가 있습니다. 내 업데이트를 참조하십시오. – henginy

+0

기본 클래스 코드가 업데이트되었습니다. ref 구현을 제거하고 목록을 반환했습니다. 여전히 같은 문제에 직면 해 있습니다. 지금 나는 정상적인 변수로 목록을 전달하지만 SplitList 메서드 내부에서 2 개의 diff 목록으로 분할하고 이러한 새 목록을 사용하여 업데이트 메서드를 호출한다고 생각합니다. 어쩌면 모의 호출이 업데이트가 호출되는지 여부를 캡처 할 수없는 이유 일 수 있습니다. – Anshul

0

가상 메서드로 클래스를 조인하면 메서드를 확인할 수 있습니다. CallBase을 사용하여 실제 메소드 (Update)를 동시에 호출 할 수도 있습니다. 다음 코드를 가정

은 (나는 분열에서 불필요한 심판을 삭제했습니다 게시 된 업데이트는 ref 매개 변수를 포함하지 않는 주어진) :

public class Type 
{ 
    public string currency { get; set; } 
    public int OrderNo { get; set; } 
} 
public class BaseClass 
{ 
    // w.r.t ref, do you mean to reassign objList to the filtered lists? 
    public void SplitList(ref IList<Type> objList) 
    { 
     var SplitA = objList.Where(c => c.currency == "USD").ToList(); 
     var SplitB = objList.Where(c => c.currency == "GBR").ToList(); 

     if (SplitA.Count() > 0) 
     { 
      Update(SplitA); 
     } 

     if (SplitB.Count() > 0) 
     { 
      Update(SplitB); 
     } 
    } 

    public virtual IList<Type> Update(IList<Type> updateList) 
    { 
     int count = 0; 
     foreach (Type objType in updateList) 
     { 
      objType.OrderNo = count++; 
     } 
     return updateList; 
    } 
} 

이 단위 테스트는 가상 Update 방법이 될 수 있음을 보여줍니다 검증 된 것은 물론 호출된다. CallBase이 아닌을 선택한 경우 목록의 요소에 대한 변이가 발생하지 않으므로 단위 테스트를 조정해야합니다.

[Test] 
public void TestSplitList() 
{ 
    var mock = new Mock<BaseClass>(); 
    mock.CallBase = true; // This will ensure the actual Update also gets called 
    IList<Type> fakeTypes = new List<Type> 
         { 
          new Type {currency = "GBR"}, 
          new Type {currency = "GBR", OrderNo = 100}, 
          new Type {currency = "JPY", OrderNo = 55} 
         }; 

    mock.Object.SplitList(ref fakeTypes); 

    mock.Verify(m => m.Update(It.IsAny<IList<Type>>()), Times.Exactly(1)); 
    mock.Verify(m => m.Update(It.Is<IList<Type>>(x => x.Any(y => y.currency == "GBR") 
       && x.Count == 2)), Times.Exactly(1)); 
    mock.Verify(m => m.Update(It.Is<IList<Type>>(
     x => x.Any(y => y.currency == "JPY"))), Times.Never); 
    Assert.AreEqual(3, fakeTypes.Count, "List itself must not have changed"); 

    // These tests show the effect of the actual `Update` method 
    Assert.IsTrue(fakeTypes.Any(t => t.OrderNo == 0 && t.currency == "GBR"), 
     "GBR must be ordered"); 
    Assert.IsTrue(fakeTypes.Any(t => t.OrderNo == 1 && t.currency == "GBR"), 
     "GBR must be ordered"); 
    Assert.IsFalse(fakeTypes.Any(t => t.OrderNo == 100 && t.currency == "GBR"), 
     "GBR must be ordered"); 
    Assert.IsTrue(fakeTypes.Any(t => t.OrderNo == 55 && t.currency == "JPY"), 
     "JPY must not be ordered"); 
} 

참고 : List 매개 변수에 대한 ref의 사용은 현재 코드 구현에 필요하지 않습니다.목록의 개체를 직접 변형하기 때문에이 변경 내용은이 항목을 참조하는 모든 컬렉션에서 볼 수 있습니다. 또한 목록 자체 (요소 만 포함)를 변경하지 않으므로 Update 매개 변수 ref을 만들거나 Update에서 반환하지 않아도됩니다.

관련 문제