2013-07-24 5 views
2

는 예외 던질 것으로 예상되는 생성자을 감안할 때 : 나는 코뿔소와 Machine.Fakes을 사용하는 방법Machine.Fakes를 사용하여 생성자가 로컬 메서드를 호출하지 않도록하려면 어떻게해야합니까?

public class MyObject 
{ 
    public MyObject(String name) 
    { 
    if (String.IsNullOrEmpty(name)) 
     throw new ArgumentNullException("name"); 

    this.Initialize(); 
    } 

    protected virtual void Initialize() 
    { 
    // do stuff 
    } 
} 

(기본값, 나는 코뿔소로 이동하고)이 클래스를 조롱하고, 그 테스트 :

  1. 그것은 예상되는 예외
  2. 을 던져 내가 실제 MyObject를 조롱 수, 초기화() MOQ와

를 호출하지 않습니다 클래스 자체와 모의 객체를 Callbase = true으로 설정하면 일반 클래스처럼 작동합니다.

난 다음이 함께 예외가 발생했다 둘 것을, 그리고 메소드가 호출되지 않았 음을 확인할 수 있습니다

// all pseudo code to prove my point of "creating an instance" 
// 
void when_creating_new_MyObject_with_null_Name_should_throw_Exception() 
{ 
    // arrange 
    Mock<MyObject> myObjectToTest = new Mock<MyObject>(String.Empty); 
    myObjectToTest.Callbase = true; 

    // act 
    Assert.Throws<ArgumentNullException>(() => 
    var instance = myObjectToTest.Object; 
); 
} 

void when_creating_new_MyObject_with_null_Name_should_not_call_Initialize() 
{ 
    // arrange 
    Mock<MyObject> myObjectToTest = new Mock<MyObject>(String.Empty); 
    myObjectToTest.Callbase = true; 

    // act 
    try 
    { 
    // creates an instance 
    var instance = myObjectToTest.Object; 
    } 
    catch {} 

    // assert 
    myObjectToTest.Verify(x => x.Initialize(), Times.Never()); 
} 

하지만이를 조롱하는 페이크 승/MSpec을 사용하는 방법을 알아내는 데 문제가 있어요 :

[Subject(typeof(MyObject), "when instantiating a new instance") 
class with_null_Name 
{ 
    static MyObject myObjectToTest; 
    static Exception expectedException; 

    Establish context =()=> 
    myObjectToTest = An<MyObject>(String.Empty); 

    Because of; // I don't think there is anything to act on here? 

    It should_throw_Exception; 
    // how to capture exception with An<T>()? 

    It should_not_call_Initialize =() => 
    myObjectToTest.WasNotToldTo(x => x.Initialize()); 

} 

내가 알고 내 Because of 행위에 일반적으로 Catch.Exception(...)를 사용합니까. 그러나이 유스 케이스는 그렇게 작동하지 않는 것 같습니다.

모든 포인터가 감사하겠습니다.

감사합니다.

면책 조항 : 실제 사용 사례는 초기화 된 무거운 물체로 인해 상당히 복잡하며 캐시 된지지 부재로는 상당히 비쌉니다. 위의 코드는 단순화 된 버전입니다.

답변

2

필자는 개인적으로 모의 프레임 워크를 사용하여 테스트 단위 내에서 모의 ​​작업을하는 데 익숙하지 않다. 의존성 주입을 사용하여 외부 의존성을 깨기 위해 모의 (mock)를 사용합니다. 나는 이것에 전문가가 결코 아니다, 그러나 나의 직감은 이것이 시험하기에 너무 세분화 된 세부 사항이다이다.

실제 상황에는 초기화 할 개체가 많이 있다고합니다. 그 중 하나 이상을 모의하고 그들이 불려지지 않았는지 확인하지 못했습니까? 또는 의존성 삽입을 사용하여 플래그를 설정할 수있는 가짜 오브젝트를 주입 할 수 있습니다.

이 제안은 모두 나에게 오히려 냄새가 난 것 같습니다. 결국 Initialize가 호출되지 않았다는 예외가 발생했는지 알 수 있습니다. 나는 미래의 편집에서 버그가 생기지 않도록하기 위해 노력하고 있다는 것을 이해하고 있다고 생각하지만 실제로 개발자를 여기에서 테스트하고 있습니까? 개인적으로 나쁜 데이터가 제공 될 때 예외가 throw되는지 확인하는 것으로 충분하다고 생각했을 것입니다. 나는 다른 의견을 듣고 싶습니다.

+0

내가 제대로 여기를 캡슐화 생각합니다. 대답으로 표시하고 (조금 리팩토링 할 것입니다). – eduncan911

+0

'내 직감은 테스트하기에 너무 세밀하다는 것입니다.'이것이 당신의 기대에 불가결 한 것이라면, 테스트하기에는 너무 세밀하지 않습니다. –

3

나에게 조롱당한 행동은 시험 방법으로 당신이 정의한 sut을 조롱했다. 실제 객체를 테스트해야합니다.
이 경우 잘못된 데이터가 제공 될 때 예외가 throw되는지 확인해야합니다.
나는 당신이하는 방법을 알고 있지만, 어쨌든 여기에 코드가 생각 :

[Subject(typeof (MyObject), "when instantiating a new instance")] 
internal class with_null_Name 
{ 
    static MyObject myObjectToTest; 
    static Exception expectedException; 

    Because of =() => expectedException = Catch.Exception(
        () => myObjectToTest = new MyObject(String.Empty)); 

    It should_fail =() => expectedException.ShouldNotBeNull(); 
} 
+0

나에게 상기시켜 줘서 고마워. 그냥 automocking 컨테이너를 활용하려고 노력하는 대신 간단한 단위 테스트를 작성할 수있다. 단지 moq를 사용하여 직접 호출 할 수있다.이 함수는'CallBase = true'를 사용하고있다. –