如果稍后验证方法被调用,在回调中执行断言是否可以接受?这是确保我的mock获取传递给它的预期参数的首选方法,还是应该在我的回调中设置局部变量并在该实例上执行断言?
我有一种情况,我在Presenter类中有一些逻辑,它根据输入派生值并将它们传递给Creator类.为了测试Presenter类中的逻辑,我想验证在调用Creator时是否遵守了正确的派生值.我想出了下面的例子,但是我不确定我是否喜欢这种方法:
[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,localWidget.DerivedName); }