如何使用Moq框架模拟ModelState.IsValid?

Maz*_*zen 83 c# asp.net-mvc unit-testing moq mocking

我正在检查 ModelState.IsValid我的控制器操作方法,它创建一个像这样的员工:

[HttpPost]
public virtual ActionResult Create(EmployeeForm employeeForm)
{
    if (this.ModelState.IsValid)
    {
        IEmployee employee = this._uiFactoryInstance.Map(employeeForm);
        employee.Save();
    }

    // Etc.
}
Run Code Online (Sandbox Code Playgroud)

我想在使用Moq Framework的单元测试方法中模拟它.我试着像这样嘲笑它:

var modelState = new Mock<ModelStateDictionary>();
modelState.Setup(m => m.IsValid).Returns(true);
Run Code Online (Sandbox Code Playgroud)

但是这在我的单元测试用例中抛出异常.有人可以帮我从这里出去吗?

Dar*_*rov 136

你不需要嘲笑它.如果您已有控制器,则可以在初始化测试时添加模型状态错误:

// arrange
_controllerUnderTest.ModelState.AddModelError("key", "error message");

// act
// Now call the controller action and it will 
// enter the (!ModelState.IsValid) condition
var actual = _controllerUnderTest.Index();
Run Code Online (Sandbox Code Playgroud)

  • @Newton,默认是真的.您无需指定任何内容即可获得真实案例.如果你想点击假案例,你只需添加一个模型状态错误,如我的回答所示. (4认同)

uad*_*ive 13

我对上述解决方案的唯一问题是,如果我设置属性,它实际上不会测试模型.我这样设置我的控制器.

private HomeController GenerateController(object model)
    {
        HomeController controller = new HomeController()
        {
            RoleService = new MockRoleService(),
            MembershipService = new MockMembershipService()
        };
        MvcMockHelpers.SetFakeAuthenticatedControllerContext(controller);

        // bind errors modelstate to the controller
        var modelBinder = new ModelBindingContext()
        {
            ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType()),
            ValueProvider = new NameValueCollectionValueProvider(new NameValueCollection(), CultureInfo.InvariantCulture)
        };
        var binder = new DefaultModelBinder().BindModel(new ControllerContext(), modelBinder);
        controller.ModelState.Clear();
        controller.ModelState.Merge(modelBinder.ModelState);
        return controller;
    }
Run Code Online (Sandbox Code Playgroud)

modelBinder对象是测试模型有效性的对象.这样我就可以设置对象的值并对其进行测试.

  • 用这样的东西孤立地测试模型不是更好吗?http://stackoverflow.com/a/4331964/3198973 (2认同)
  • 虽然这是一个聪明的解决方案,但我同意@Ru​​bberDuck。为了使它成为一个实际的,独立的单元测试,模型的验证应该是其自己的测试,而控制器的测试应该具有其自己的测试。如果模型更改违反了ModelBinder验证,则控制器测试将失败,这是误报,因为控制器逻辑未中断。要测试无效的ModelStateDictionary,只需添加一个虚假的ModelState错误,以使ModelState.IsValid检查失败。 (2认同)