如果稍后验证方法被调用,在回调中执行断言是否可以接受?这是确保我的mock获取传递给它的预期参数的首选方法,还是应该在我的回调中设置局部变量并在该实例上执行断言?
@H_404_22@解决方法
我有一种情况,我在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);
- }