2014-02-12 4 views
4

다른 함수에서 호출 된 함수의 결과를 조롱하거나 패닉시킬 수 있습니까? 보통 Test2는 실제 데이터를 가져 오지 않는 DataAccess 메소드입니다. unittest에서 테스트하는 것이 비즈니스 논리입니다.FakeItEasy로 메소드 내의 메소드 조롱

이것은 내가 지금 가지고 있지만 전혀 작동하지 않는 것입니다. 합은 항상 5로 단정됩니다!

public int Test1() 
{ 
    var value = this.Test2(); //Unittest should substitute with 5 
    var businesslogic = value + 10; //The business logic 

    return businesslogic; 
} 

public int Test2() 
{ 
    return 10; //I try to mock this value away in the test. Don´t go here! 
} 

그런 다음 "비즈니스 로직"에서 실행하고 싶은 Unittest가 있습니다.

[TestMethod()] 
public void TestToTest() 
{ 
//Arrange 
var instance = A.Fake<IClassWithMethods>(); 

     //Make calling Test2 return 5 and not 10. 
A.CallTo(() => instance.Test2()).Returns(5); 

     //Call the method 
var sum = instance.Test1(); 

//Assert if the business logic in the method works. 
Assert.AreEqual(15, sum); 
} 

답변

3

먼저 A.에게 테스트 제가 호출되지 않을 수 있습니다 특히 인터페이스 꾀병

  1. 는 "내부 방법"을 의미하는 방법에 대한 환상적인 점 Tseng's answer에 있다고 생각 말할 수 있도록 B를 조롱 할 수 있습니다 , 및
  2. 내부 가짜 종속성이 있어야합니다. 이 변경을 할 수있는 옵션이있는 경우 지금 바로 내 대답 읽기를 중단하십시오.

    1. 해야 Test1 반환 businessLogic : 당신은 여전히 ​​

    을 읽는 경우에, 나는 두 가지에 대한 혼란 스러워요? 이 쓰여으로 (컴파일 에러가 해결되면), 나는 돌아 Test1을 기대 5 (안 15) 때 Test2 반환 당신이 Returns(5)Test2에 설정하고이 위조 때문에 다음 Test1를 호출 5. TestToTest에서

  3. , 인터페이스, 나는 합계가 0, int에 대한 기본값으로 될 것으로 기대합니다. 나는 당신이 어떻게 5를 얻을 것인지 모르겠다.사실,이 시험에서이 동작을 복제 한 : 당신이 정말로 ClassWithMethods에 교체 코드를 갖고 싶어

[TestMethod] 
public void TestToTestInterface() 
{ 
    //Arrange 

    var instance = A.Fake<IClassWithMethods>(); 

    //Make calling Test2 return 5 and not 10. 
    A.CallTo(() => instance.Test2()).Returns(5); 

    //Call the method 
    var sum = instance.Test1(); 

    //Assert if the business logic in the method works. 
    Assert.AreEqual(0, sum); // because Test1 wasn't faked 
} 

나는, 접근 자신을 상관하지 않지만

  1. 우리는 Test1Test2,289,192을해야하고 Test1 방법을 테스트하는 방법이, 또는 그들은 거짓 될 수 없습니다.
  2. 가짜 ClassWithMethods이 아니라 IClasssWithMethods입니다.
  3. Test1이 호출 될 때 원래 코드 (가짜 Test2)를 호출해야합니다.

나는 모두 함께 이러한 변경 사항을 넣어했으며,이 테스트는 나를 위해 전달합니다

public class ClassWithMethods : IClassWithMethods 
{ 
    public virtual int Test1() 
    { 
     var value = this.Test2(); //Unittest should substitute with 5 
     var businesslogic = value + 10; //The business logic 

     return businesslogic; 
    } 

    public virtual int Test2() 
    { 
     return 10; //I try to mock this value away in the test. Don´t go here! 
    } 
} 

[TestMethod] 
public void TestToTestClass() 
{ 
    //Arrange 

    var instance = A.Fake<ClassWithMethods>(); 

    //Make calling Test2 return 5 and not 10. 
    A.CallTo(() => instance.Test2()).Returns(5); 

    // Make sure that Test1 on our fake calls the original ClassWithMethods.Test1 
    A.CallTo(() => instance.Test1()).CallsBaseMethod(); 

    //Call the method 
    var sum = instance.Test1(); 

    //Assert if the business logic in the method works. 
    Assert.AreEqual(15, sum); 
} 
+1

멋진 대답을. 첫 번째 질문에 대답하기 위해 질문에 내 코드를 수정했습니다. 하지만 관계없이이 정확한 예제에서 무엇을 진짜로하려고하는 것은 거기에 호출되는 다른 메서드를 호출하지 않고 메서드에서 논리를 테스트 할 수있게하는 것입니다. 만약 내가 Test2에서 데이터베이스에 몇 가지 삽입했다 나는 그것을 부르고 싶지 않다. 메서드를하지만 "값 + 10"메서드의 비즈니스 논리를 테스트 할 수 싶습니다. 나는 가상 솔루션이 마음에 들지 않는다는 것에 동의한다. – Sturla

+1

어떤 방법을 바꾸고 싶지 않다면 원하는 테스트를 어떻게 수행 할 수 있는지 보지 못합니다. my와 Tseng의 제안은 Tseng의 코드가 좀 더 극적 (그리고 우월하다고 생각합니다.)으로 코드를 수정해야합니다. 나는 당신이 [TypeMock Isolator] (http://www.typemock.com/isolator-product-page) 또는 [Microsoft Fakes] (http://msdn.microsoft.com/ko/)와 같은 조롱 프레임 워크를 사용해야 할 것이라고 생각합니다. -us/library/hh549175 (v = vs.110) .aspx)를 수정해야합니다. –

+0

대단히 감사합니다. Microsoft Fakes는 제가 찾고 있던 것입니다. 여기에 그것을 사용하기 시작하는 훌륭한 링크 http://www.codeproject.com/Articles/582812/Unit-testing-with-Fakes-with-Visual-studio-Premium – Sturla

3

내가 아는 한 그렇게 할 수 없습니다.

instance은 실제 클래스의 인스턴스가 아니며 인터페이스의 모형 만 사용하므로 instance.Test1()을 호출해도 위에 설명한 코드가 호출되지 않습니다. 그러나 UnitTest Test2 메서드는 자체 테스트가 가능합니다.

그러나 할 수있는 것은 2 단위 테스트를하는 것입니다.

첫 번째 테스트 (테스트 방법 Test2)에서 필요한 종속성을 사용하여 클래스를 인스턴스화하거나 특정 값/매개 변수와의 종속성이없는 경우 클래스를 인스턴스화합니다.

그런 다음 동일한 입력 매개 변수로 두 번째 테스트를 수행하고 Test() 테스트 방법을 수행하십시오.

모형은 인터페이스 (이 클래스는 외부에서 인스턴스화 된 )에서 실습해야하는 종속성에만 사용됩니다. 예를 들어 ClassA이고 ClassB이고 ClassA 인 경우 IClassB 인터페이스에 따라 다릅니다. 그런 다음,