2009-09-08 2 views
1
여기

내 상황 : 다음 클래스에 내가에 테스트 할 "HasSomething()"함수 : 그래서Rhino Mock을 사용하여 로컬 함수 호출을 모의하는 방법?

public class Something 
{ 
     private object _thing; 

     public virtual bool HasSomething() 
     { 
      if (HasSomething(_thing)) 
       return true; 
      return false; 
     } 

     public virtual bool HasSomething(object thing) 
     { 
      ....some algo here to check on the object... 
      return true; 
     } 
} 

, 내가 이렇게 될 내 테스트를 작성 :

public void HasSomethingTest1() 
    { 
     MockRepository mocks = new MockRepository(); 

     Something target = mocks.DynamicMock(typeof(Something)) as Something; 

     Expect.Call(target.HasSomething(new Object())).IgnoreArguments().Return(true); 

     bool expected = true; 
     bool actual; 
     actual = target.HasSomething(); 

     Assert.AreEqual(expected, actual); 
    } 

테스트가 올바르게 작성 되었습니까? 예상대로 결과를 얻을 수 없으므로 도와주세요. "HasSomething (객체)"는 그런 식으로 조롱 할 수 없습니다. 그것은 기대치에 못 미치는 것으로 '사실'을 돌려주지 않았다.

감사합니다.

답변

2

OP의 '대답'에 대한 응답 : RhinoMocks는 모의 수업을 작성하지 않고 모의 수업을 만들고 그 회원 (예 : 속성 및 기능)에 대한 기대치 및 준비된 응답을 설정할 수 있습니다. . mock/stub 클래스의 멤버 함수를 테스트하려고하면 구현보다는 조롱 프레임 워크를 테스트 할 위험이 있습니다.

논리 경로의 특정 시나리오가 로컬 (일반적으로 개인) 함수의 반환 값에 의존하는 경우 해당 로컬 함수에서 요구하는 반환 값에 영향을주는 외부 종속성 (다른 개체)이 실제로 필요합니다 . 위의 코드 스 니펫의 경우 다음과 같이 테스트를 작성합니다.

[Test] 
public void TestHasSomething() 
{ 
    // here I am assuming that _thing is being injected in via the constructor 
    // you could also do it via a property setter or a function 
    var sut = new Something(new object()); 
    Assert.IsTrue(sut.HasSomething); 
} 

즉 조롱이 필요하지 않습니다.


이것은 내가 조롱과 관련하여 자주 과거에 가졌던 오해의 한 가지 점입니다. 우리는 테스트중인 시스템 (SUT)의 의존성에 대한 행동을 조롱합니다. SUT는 종속성에 대한 여러 가지 방법을 호출하고 조롱 프로세스는 논리가 흐르는 방식을 안내하기 위해 미리 준비된 응답을 제공합니다 (데이터베이스 등으로가는 것보다).

간단한 예제는 다음과 같습니다 (이 테스트에는 RhinoMocks AAA 구문을 사용했음을 유의하십시오.) 코드 샘플에서 사용하는 구문이 Record-Replay 패러다임을 사용하고 있음을 확인합니다. !

public class SUT 
{ 

    Dependency _depend 

    public SUT (Dependency depend) 
    { 
     _depend = depend; 
    } 

    ... 

    public int MethodUnderTest() 
    { 
     if (_depend.IsReady) 
       return 1; 
     else 
       return -1; 
    } 
} 

... 

[Test] 
public void TestSUT_MethodUnderTest() 
{ 
    var dependency = MockRepository.GenerateMock<Dependency>(); 

    dependency.Stub(d => d.IsReady).Return(true); 

    var sut = new SUT(dependency); 
    Assert.AreEqual(1, sut.MethodUnderTest()); 
} 

을 그리고 당신이 가지고있는 문제는 당신이 조롱 개체의 동작을 테스트하려고하는 것입니다 : 그것은 기록을 사용하고 다시 재생되지 않는다는 그건 아마도)뿐만 아니라 문제가 발생할 것입니다. 즉, 실제로 수업을 테스트하지는 않습니다.

+0

등의 조롱 객체가 SUT로 전달되어야 스터브 부분 모의 전환. something.HasSomething (mockedObject); –

0

이와 같은 경우, 테스트 double은 Something 클래스의 파생 버전이어야합니다. 그런 다음 HasSomething (객체) 메서드를 재정의하고 HasSomething()이 해당 메서드를 호출하는지 확인합니다.

0

정확하게 이해한다면 실제로 HasSomething에 대한 알고리즘을 고려하지 않고 HasDynamicFlow 메서드를 테스트하는 데 관심이 있습니다 (위 예제에 나와 있지 않음).

Preet는 간단하게 Something의 하위 클래스를 만들고 HasSomething의 동작을 재정 의하여 알고리즘을 단락 할 수 있지만 Rhino가 효율적으로 제거 할 수있는 몇 가지 추가 테스트 더미 코드를 만들어야한다는 점에서 옳습니다.

동적 모의 대신 Partial Mock Stub을 사용하는 것이 좋습니다.스텁은 덜 엄격하며 Properties로 작업하는 데 이상적입니다. 그러나 방법은 약간의 추가 노력이 필요합니다.

[Test] 
    public void CanStubMethod() 
    { 
     Foo foo = MockRepository.GenerateStub<Foo>(); 

     foo.Expect(f => f.HasDynamicFlow()).CallOriginalMethod(OriginalCallOptions.NoExpectation); 
     foo.Expect(f => f.HasSomething()).CallOriginalMethod(OriginalCallOptions.NoExpectation); 
     foo.Expect(f => f.HasSomething(null)).IgnoreArguments().Return(true); 

     Assert.IsTrue(foo.HasDynamicFlow()); 
    } 

EDIT : 추가 코드 예와 말한다 jpoh

관련 문제