2011-04-15 12 views
2

的方法我在使用ref參數存根方法時存在問題。
我想爲某個輸入值存根方法,並檢查它是否被調用。
我嘗試:AssertWasCalled和存根引用參數

// Variables needed - can be skipped 
var activity = MockRepository.GenerateMock<ICompositeActivity<object>>(); 
var context = new Context<object>(new object()); 
var inputValue = MockRepository.GenerateMock<IActivity<object>>(); 
var outputValue = MockRepository.GenerateMock<IActivity<object>>(); 
var executeCalled = 0; 

// The stub: 
activity.Stub(
    x => 
    x.Execute(Arg<Context<object>>.Is.Same(context), 
       ref Arg<IActivity<object>>.Ref(Is.Same(inputValue), outputValue).Dummy)) 
    .WhenCalled(i => ++executeCalled).Return(true); 

var tmp = inputValue; 
tmp.ShouldBeTheSameAs(inputValue); 

// The execution: 
activity.Execute(context, ref tmp); 

// The check: 
inputValue.ShouldNotBeTheSameAs(outputValue); // Passes, ok 
tmp.ShouldBeTheSameAs(outputValue); // Passes, ok 
executeCalled.ShouldEqual(1); // Passes, ok 

// Passes. Why? 
activity.AssertWasCalled(
    x => 
    x.Execute(Arg<Context<object>>.Is.Same(context), 
       ref Arg<IActivity<object>>.Ref(Is.Same(outputValue), null).Dummy)); 

// Doesn't pass. Why? 
activity.AssertWasCalled(
    x => 
    x.Execute(Arg<Context<object>>.Is.Same(context), 
       ref Arg<IActivity<object>>.Ref(Is.Same(inputValue), outputValue).Dummy)); 

BTW:我知道,那本次測試沒有任何意義,因爲它不會測試任何真正的類。這是我真實測試的一個精簡版本來說明問題。

正如你所看到的,有什麼奇怪的事情:

execute方法的存根是正確的,它是所謂的,因爲executeCalled是1和tmp參數已經從inputValue改爲outputValue
BUT:

  • AssertWasCalled第一檢查通過,儘管它會檢查,Execute是否被調用outputValue,它不是。
  • 第二單向帶AssertWasCalledfailes,儘管它會檢查,Execute是否被調用inputValue的,這是。

而且,當我檢查i.Arguments[1]內存根WhenCalled,它是outputValue,不inputValue ......它看起來像犀牛嘲笑被改變輸入值,以指定的返回值,甚至稱存根之前.. 。

這是Rhino Mocks中的一個bug嗎?或者我錯過了什麼?如果它是一個錯誤,是否有任何解決方法,除了executeCalled計數器?

+2

請問downvoter請詳細說明一下嗎? – 2011-04-15 11:41:00

+0

我同意丹尼爾..解釋.. – 2011-04-15 12:13:58

回答

2

相同的測試,有點清理:

public interface IX 
    { 
     void Execute(ref object param); 
    } 

    [TestMethod] 
    public void TestMethod() 
    { 
     // Variables needed - can be skipped 
     var inputValue = new object(); 
     var outputValue = new object(); 
     IX activity = MockRepository.GenerateMock<IX>(); 

     // The stub: 
     activity 
      .Stub(x => x.Execute(
       ref Arg<object>.Ref(Is.Same(inputValue), outputValue).Dummy)); 

     var tmp = inputValue; 

     activity.Execute(ref tmp); 

     activity 
      .AssertWasCalled(x => x.Execute(
       ref Arg<object>.Ref(Is.Same(outputValue), null).Dummy)); 
    } 

它傳遞。它清楚地表明Rhino記錄輸出值,而不是原始輸入值。它很少被認可,因爲你需要這個臨時變量來測試這種效果。

下面的測試也通過:

[TestMethod] 
    public void TestMethod() 
    { 
     // Variables needed - can be skipped 
     var inputValue = new object(); 
     var outputValue = new object(); 
     IX activity = MockRepository.GenerateMock<IX>(); 

     // The stub: 
     activity 
      .Stub(x => x.Execute(
       ref Arg<object>.Ref(Is.Same(inputValue), outputValue).Dummy)); 

     activity.Execute(ref inputValue); 

     activity 
      .AssertWasCalled(x => x.Execute(
       ref Arg<object>.Ref(Is.Same(inputValue), null).Dummy)); 
    } 

它可以被看作是一個錯誤,但還是比較微妙的情況。如果確實存在問題,您可以查看Rhinos代碼以查看該錯誤是否容易修復。

+0

感謝您花時間回答我的問題。但是,它並沒有幫助。第一個代碼只是證實了我的觀察。第二代碼實際上是相同的,第一,因爲'的ReferenceEquals(inputValue的,outputValue)'將調用'activity.Execute'後返回TRUE;,所以'inputValue'可以'outputValue'在斷言進行交換。我想說的是:你的第二個代碼測試與第一個代碼相同。但它不檢查是否Execute''叫用'inputValue' ... – 2011-04-19 17:08:02

+0

@Daniel原值:我知道......所有這些都是我的回答的全部目的。我清理了測試以便更容易地顯示並證明效果。第二個測試只是爲了說明開發者到目前爲止可能錯過了效果。 – 2011-04-19 18:00:31

+0

我不能說更多。您會遇到這種效果,我只能通過使用最小代碼進行復制來批准它。你的問題是:「我錯過了什麼?」我的回答是:「不,它在那裏,可能被認爲是一個錯誤。」 – 2011-04-19 18:07:18