首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Moq:模拟IValidatableObject的实现?

Moq:模拟IValidatableObject的实现?
EN

Stack Overflow用户
提问于 2015-12-15 08:30:51
回答 2查看 196关注 0票数 0

假设我有一个方法,它希望从IValidatableObject的具体实例中提取ValidationResults,并将它们粘贴到else...say的某个位置,从DTO到控制器的ModelState。

如何开始模拟实现IValidatableObject的对象?

比方说,我有一些这样的代码(还没有编译):

代码语言:javascript
复制
[Test]
public void GivenBadObjectMethodShouldTransferErrorsToModelstate()
{
  // Mock BadObject and controller
  var controller = new Controller(); 
  var badObject = new Mock<ObjectImplementingIValidatableObject>();
  badObject.Setup( x => x.Validate(It.IsAny<ValidationContext>() )
           .Returns( new List<ValidationResult> { new ValidationResult("error") });

  // Invoke the method
  controller.TransferErrorsToModelStateFrom(badObject);

  // Check that ModelState contains the errors expected
  Assert.IsTrue(controller.ModelState.ContainsKeys("error") );
}

我遇到的一个问题是ValidationContext,得到如下错误: System.NotSupportedException:在非虚拟成员上的无效设置x => x.Validate(It.IsAny())

你能提供一些关于如何更好地解决这个问题的见解吗?

谢谢,

克里斯

EN

回答 2

Stack Overflow用户

发布于 2015-12-15 14:59:51

您正在模拟ObjectImplementingIValidatableObject 具体类型。这可能不是一个接口,它的验证方法被声明为非虚拟。这是大多数隔离框架无法处理的情况,因为它们通过在运行时动态生成模拟类型的子类(或实现)来工作。

如果您提供了一个要模拟的接口,隔离框架会在运行时生成一个假的实现。如果您提供了一个具体的类型,那么您存根/模拟的方法必须是虚拟的,这样框架才能在动态创建的子类中覆盖它们。

因此,为了让您的代码片段正常工作,可以考虑使用接口(可能只是IValidatableObject),或者使在ObjectImplementingIValidatableObject上声明的Validate方法成为虚拟方法。

票数 1
EN

Stack Overflow用户

发布于 2015-12-16 01:59:10

在所有这些东西中游荡时,很容易忽略对接口的编程。谢谢你的帮忙!

这是我最终得到的代码:(我已经包含了所有内容,尽管有些部分我可以提取到一个setup方法中)

代码语言:javascript
复制
[Test]
    public void GivenValidatableObjectWithMemberErrorThenMethodShouldTransferMemberErrorToModelstate()
    {
        // Setup, getting protected member of abstract class instance
        var controller = (TestConcreteController)FormatterServices
            .GetUninitializedObject(typeof(TestConcreteController));

        MethodInfo ApplyErrorsToModelStateFromModel = controller
            .GetType()
            .GetMethod("ApplyErrorsToModelStateFromModel",
            BindingFlags.Instance | BindingFlags.NonPublic);

        // Setup, building expected objects to pass into method
        IEnumerable<ValidationResult> errors = new List<ValidationResult> 
        { 
            new ValidationResult(TestConstant.ExpectedErrorMessage, TestConstant.ExpectedMembers)
        };

        var objectWithMemberError = new Mock<IValidatableObject>();
        objectWithMemberError.Setup(x => x.Validate(It.IsAny<ValidationContext>()))
                             .Returns(errors);

        // Call the method
        ApplyErrorsToModelStateFromModel.Invoke(controller, new[] { objectWithMemberError.Object });

        // Check that member was added to list and contains the expected error
        Assert.IsTrue(controller.ModelState[TestConstant.ExpectedMembers[0]].Errors[0].ErrorMessage == TestConstant.ExpectedErrorMessage);
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34279075

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档