2011-04-10 2 views
9

Roy Osherove의 The Art of Unit Testing을 읽는 동안 Rhino-Mocks (3.6)를 실험하기 시작했습니다. 그는 조롱 된 메서드가 같은 매개 변수를 사용하여 두 번 호출 될 때 다른 결과를 반환하도록 스크립팅 할 수 있음을 보여주는 예제가 있습니다.Rhino-Mock 스텁으로 주문 값 반환 값

[Test] 
    public void ReturnResultsFromMock() 
    { 
     MockRepository repository = new MockRepository(); 
     IGetRestuls resultGetter = repository.DynamicMock<IGetRestuls>(); 
     using(repository.Record()) 
     { 
      resultGetter.GetSomeNumber("a"); 
      LastCall.Return(1); 

      resultGetter.GetSomeNumber("a"); 
      LastCall.Return(2); 

      resultGetter.GetSomeNumber("b"); 
      LastCall.Return(3); 

     } 

     int result = resultGetter.GetSomeNumber("b"); 
     Assert.AreEqual(3, result); 

     int result2 = resultGetter.GetSomeNumber("a"); 
     Assert.AreEqual(1, result2); 

     int result3 = resultGetter.GetSomeNumber("a"); 
     Assert.AreEqual(2, result3); 
    } 

이 작업은 정상적으로 작동합니다. "퍼스트 콜은"이기 때문에,이 테스트는 실패

[Test] 
    public void StubMethodWithStringParameter_ScriptTwoResponses_SameResponseReceived() 
    { 
     MockRepository mocks = new MockRepository(); 
     IMessageProvider stub = mocks.Stub<IMessageProvider>(); 

     using (mocks.Record()) 
     { 
      stub.GetMessageForValue("a"); 
      LastCall.Return("First call"); 
      stub.GetMessageForValue("a"); 
      LastCall.Return("Second call"); 
     } 

     Assert.AreEqual("First call", stub.GetMessageForValue("a")); 
     Assert.AreEqual("Second call", stub.GetMessageForValue("a")); 
    } 
} 

public interface IMessageProvider 
{ 
    string GetMessage(); 
    string GetMessageForValue(string value); 
} 

: 나는 스텁하고 받아 문자열을 반환하는 방법으로 같은 일을하려고 할 때, 나는 두 번째 반환 값을 생성 할 수 없습니다입니다 두 통화 모두 수신 됨. 구문의 여러 주름 (mocks.Ordered(), SetResult, Expect 등 사용)을 시도했지만 여전히 두 번째 결과가 나타나지 않습니다.

Rhino-Mocks에서 잘못된 점이 있습니까? 아니면 제한입니까? 이 blog post을 확인했지만 제안 된 구문으로 내 문제가 해결되지 않았습니다.

답변

10

당신이 놓치고있는 비트는 첫 번째 값은 한 번만 반환해야 스텁 말할 것입니다 : 당신의 "두 번째 호출은"정말하지 않는 한 "이후 두 번째 또는 통화"를 의미 물론

... 
using (mocks.Record()) 
{ 
    stub.GetMessageForValue("a"); 
    LastCall.Return("First call").Repeat.Once(); 
    stub.GetMessageForValue("a"); 
    LastCall.Return("Second call"); 
} 

을 반복과 함께 다른 제한 사항을 부과합니다.

또한 고려할 수 있습니다

정렬, 법, 어설는 (AAA) 구문 RhinoMocks 지금 제공하는 새로운 :

[Test] 
public void StubMethodWithStringParameter_ScriptTwoResponses_SameResponseReceived() 
{ 
    IMessageProvider stub = MockRepository.GenerateStub<IMessageProvider>(); 

    stub.Expect(mp => mp.GetMessageForValue("a")) 
     .Return("First call") 
     .Repeat.Once(); 
    stub.Expect(mp => mp.GetMessageForValue("a")) 
     .Return("Second call"); 

    Assert.AreEqual("First call", stub.GetMessageForValue("a")); 
    Assert.AreEqual("Second call", stub.GetMessageForValue("a")); 
} 

그것은 좀 더 간결이고 일반적으로 기록 재생 - 대한 걱정에서 당신을 저장 스텁의 상태를 주장한다. Derick Bailey는 Los Techies에 article about using Repeat이라고 썼습니다. AAA 구문을 사용하는 경우도 있습니다).

+1

씨 - 퍼티 @, 감사합니다! Repeat.Once()는 멋지게 작동합니다. –

+0

기사에 +1 ... 나는 잠시 동안 좋은 종합적 설명을 찾고있다. :) –

1

당신이 기대하고 싶지 않지만 의존성을 대체하기 때문에 당신이 스텁으로 작업한다면 Expect가 적합하지 않다고 생각합니다.

그래서 난 당신이 스텁 구문을 사용하는 경우가 더 의미가 생각 :

stub.Stub.(s=>s.GetMessageForValue("a")) 
          .Return("First call").Repeat.Once(); 

stub.Stub.(s=>s.GetMessageForValue("a")) 
          .Return("Second call").Repeat.Any;