2010-07-12 25 views
14

我是新來的嘲笑,而且我很難用UnitTesting解決一個問題。我該如何使用Rhino Mocks來檢查傳遞給方法的值是什麼

說我有這樣的代碼:

public class myClass{ 

    private IDoStuff _doer; 

    public myClass(IDoStuff doer){ 
     _doer = doer; 
    } 

    public void Go(SomeClass object){ 

     //do some crazy stuff to the object 

     _doer.DoStuff(object) //this method is void too 
    } 
} 

好了,我想單元測試Go方法。我不關心_doer對象在獲取它時對對象做了什麼。

但是我確實想要檢查_doer對象收到了什麼。

僞代碼,我想要實現這個

[Test] 
public void MyTest() 
{ 
    IDoStuff doer = Mocker.Mock<IDoStuff>(); 
    Guid id = Guid.NewGuid(); 

    //test Go method 
    new MyClass(doer).Go(new SomeClass(){id = id}); 

    Assert.AreEqual(id,MockingFramework.Method(DoStuff).GetReceived<SomeClass>().id); 
} 

這可能使用犀牛,如果是這樣,我怎麼實現的呢?

歡呼

回答

21

有了新的排列/法/斷言語法:

[Test] 
public void MyTest() 
{ 
    // arrange 
    IDoStuff doer = MockRepository.GenerateStub<IDoStuff>(); 
    MyClass myClass = new Myclass(doer); 
    Guid id = Guid.NewGuid(); 

    // act 
    myClass.Go(new SomeClass(){id = id}); 

    // assert 
    doer.AssertWasCalled(x => x.DoStuff(
     Arg<Someclass>.Matches(y => y.id == id))); 
} 
4

我覺得你有什麼好所以它會是:

IDoStuff doer = MockRepository.GenerateMock<IDoStuff>(); 

然後通過設置的期望:

doer.Expect(() => DoStuff(id)); 

然後在最後:

doer.VerifyAllExpectations(); 

EDITED from Lee's答案要注意的是,你還可以做的東西,如:

doer.Expect(d => d.DoStuff(Arg<int>.Is.GreaterThan(5)) 

​​

,或者當您不想使用精氨酸和精氨酸的對象確切的參考比較類似的測試。

1

如果你只是想測試的MyClass實例傳遞它的參數來doer.Go那麼你可以建立一個預期:

SomeClass obj = new SomeClass { id = id }; 

doer.Expect(d => d.DoStuff(obj)); 

//test go method 
new MyClass(doer).Go(obj); 

doer.VerifyAllExpectations(); 

但是,如果你要檢查它通過一些可能不同的對象有一些爲屬性特定的值,那麼你可以使用約束:

doer.Expect(d => d.DoStuff(null)) 
    .IgnoreArguments() 
    .Constraints(Property.Value("Id", expectedId)); 
7

所有這些答案提供了各種方法來做你想做的事情,所有這些工作。還有一件事要注意。如果你需要得到真正的「低級別」並檢查傳遞給任何存根/模擬方法的參數,可以使用GetArgumentsForCallsMadeOn

因爲它返回對象[] [],所以有點麻煩。您可以使用它像這樣(假設你存根stubber.InsertData接受NULL):

var args = stubber.GetArgumentsForCallsMadeOn(s => s.InsertData(null)); 

ARGS [0]是傳遞給InsertData第一次,它被稱爲參數數組。

args [1]是第二次調用時傳遞給InsertData的參數數組。

等等

所以,如果你想看到的是一些方法你可以在第一次調用的第二個參數傳遞的整數值:

var check = (int) args[0][1]; 

同樣,我建議一個以前的方法,但是如果你需要真正的沮喪和骯髒來檢查參數,這是可用的。

3

只有一個建議:

Wim CoenenPatrick Steele兩個解決方案是正確的,但對於第一種解決方案,非常快的時候,只有一個參數,當測試失敗有不正確的錯誤消息。

這是我的功能有兩個參數的消息:

IProductChecker.MustPublish(等於2,等於123X);預期#1,實際#0。

現在,這兩個參數哪個是錯的?那麼如果參數更多呢?

我準備測試與驗證碼:

//ARRANGE 
const string CLASSCODE = "ABC"; 
const string SUBCLASSCODE = "123X"; 
var expected = new [] {CLASSCODE, SUBCLASSCODE}; 

//ACT 
SUT.CallMyFunction(chkMock); 
var actual = chkMock.GetArgumentsForCallsMadeOn(m => m.MustPublish(null, null))[0]; 

//Assert 
CollectionAssert.AreEqual(expected, actual); 
//instead of 
//chkMock.AssertWasCalled(m => m.MustPublish(Arg<string>.Is.Equal("2"), Arg<string>.Is.Equal(SUBCLASSCODE))); 

因此,在這種情況下,消息是:

CollectionAssert.AreEqual失敗。 (索引0處的元素不匹配。)

相關問題