如果稍後驗證方法是否被調用,在回調中進行斷言是否可接受?這是確保我的模擬獲得傳遞給它的預期參數的首選方法,還是應該在回調中設置局部變量並在該實例上執行斷言?驗證傳遞給模擬參數的正確方法是按預期方式設置
我有一種情況,我在Presenter類中有一些邏輯,它根據輸入派生值並將它們傳遞給Creator類。爲了測試Presenter類中的邏輯,我想驗證在創建者被調用時觀察到適當的派生值。我想出了下面的作品的例子,但我不知道我是否喜歡這種方法:
[TestFixture]
public class WidgetCreatorPresenterTester
{
[Test]
public void Properly_Generates_DerivedName()
{
var widgetCreator = new Mock<IWidgetCreator>();
widgetCreator.Setup(a => a.Create(It.IsAny<Widget>()))
.Callback((Widget widget) =>
Assert.AreEqual("Derived.Name", widget.DerivedName));
var presenter = new WidgetCreatorPresenter(widgetCreator.Object);
presenter.Save("Name");
widgetCreator.Verify(a => a.Create(It.IsAny<Widget>()), Times.Once());
}
}
我很擔心,因爲沒有在年底Verify
電話,也不能保證斷言回調將被調用。另一種方法是設置一個局部變量的回調:
[Test]
public void Properly_Generates_DerivedName()
{
var widgetCreator = new Mock<IWidgetCreator>();
Widget localWidget = null;
widgetCreator.Setup(a => a.Create(It.IsAny<Widget>()))
.Callback((Widget widget) => localWidget = widget);
var presenter = new WidgetCreatorPresenter(widgetCreator.Object);
presenter.Save("Name");
widgetCreator.Verify(a => a.Create(It.IsAny<Widget>()), Times.Once());
Assert.IsNotNull(localWidget);
Assert.AreEqual("Derived.Name", localWidget.DerivedName);
}
我覺得這種做法是不容易出錯,因爲它是更加明確,而且更容易地看到,Assert
語句將被調用。一種方法比另一種更好嗎?有沒有更簡單的方法來測試傳遞給我缺少的模擬的輸入參數?
如果它是有幫助的,這裏是代碼的這個例子的其餘部分:
public class Widget
{
public string Name { get; set; }
public string DerivedName { get; set; }
}
public class WidgetCreatorPresenter
{
private readonly IWidgetCreator _creator;
public WidgetCreatorPresenter(IWidgetCreator creator)
{
_creator = creator;
}
public void Save(string name)
{
_creator.Create(
new Widget { Name = name, DerivedName = GetDerivedName(name) });
}
//This is the method I want to test
private static string GetDerivedName(string name)
{
return string.Format("Derived.{0}", name);
}
}
public interface IWidgetCreator
{
void Create(Widget widget);
}
編輯
我更新的代碼,使我的問題概括更容易使用第二種方法。我將Setup/Verify中使用的表達式創建爲一個單獨的變量,所以我只需要定義一次。我覺得這個方法是我最熟悉的,它很容易設置,並且出現錯誤信息時失敗。
[Test]
public void Properly_Generates_DerivedName()
{
var widgetCreator = new Mock<IWidgetCreator>();
Widget localWidget = null;
Expression<Action<IWidgetCreator>> expressionCreate =
(w => w.Create(It.IsAny<Widget>()));
widgetCreator.Setup(expressionCreate)
.Callback((Widget widget) => localWidget = widget);
var presenter = new WidgetCreatorPresenter(widgetCreator.Object);
presenter.Save("Name");
widgetCreator.Verify(expressionCreate, Times.Once());
Assert.IsNotNull(localWidget);
Assert.AreEqual("Derived.Name", localWidget.DerivedName);
}
我同意第二種方法更可取。我喜歡@ aqwert的使用驗證的建議,但失敗消息太難以處理。我在原始問題中添加了一些代碼來更新第二種方法,因此我只需要聲明一次表達式。想想我會堅持這種做法。 – rsbarro 2011-04-23 04:36:43