asp.net core mvc控制器单元测试时使用TryUpdateModel
本文关键字:TryUpdateModel 单元测试 控制器 net core mvc asp | 更新日期: 2023-09-27 18:05:07
在asp.net核心应用程序中,我有一对响应Edit操作的控制器方法。一个用于GET,它接受实体id的字符串参数:
public async Task<IActionResult> Edit(string id)
,另一个用于接收更新实体值的POST:
[HttpPost]
[ActionName("Edit")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> EditSave(string id)
在postable action方法中,我调用
var bindingSuccess = await TryUpdateModelAsync(vm);
这很好。
现在,我正试图为此编写一个测试,但我发现TryUpdateModelAsync
需要HttpContext
和控制器的许多东西来充实。我试过模拟这些,但在看了TryUpdateModelAsync
的源代码后,我意识到我基本上需要模拟所有的元数据,这并不是直接的。
我想知道如果也许这个困难是告诉我的东西:TryUpdateModelAsync
使它难以测试,所以我应该重构控制器方法,不依赖于这个助手。相反,我可以为我的视图模型的方法添加另一个参数,并用[FromBody]
修饰它,这样,当post字段出现时,模型绑定就会发生,但在测试时,我将能够传入视图模型。但是,我喜欢TryUpdateModelAsync
方法,因为它完成了将post字段合并到视图模型中的繁忙工作。我能想到的另一种完成合并的方法是编写我自己的Merge方法。好吧,没什么大不了的,但我不希望为每个实体都这样做(或者重新发明轮子,编写基于反射的合并),真的,我想知道我是否错过了如何编写针对此的单元测试的船。我可以启动一个完整的TestServer
,就像我为集成测试所做的那样,但我不确定这是正确的方向,感觉我只会进一步复杂化我的单元测试。然而,也许在这种情况下是合理的?
我已经看到了与以前版本的。net mvc工作的答案,他们所需要做的就是模拟IValueProvider
并将其附加到控制器上,但在。net核心中,TryUpdateModelAsync
似乎被重新制作,需要更多的移动部件。
- 继续嘲笑和存根所有的碎片
TryUpdateModelAsync
需求。这似乎是个死胡同 - 使用
TestServer
,使这个测试从一点点使用HttpClient
更高的高度 - 重构此方法以使用
[FromBody]
上的视图模型参数,然后写我自己的合并每个实体的方法,在那里进行并行步进TryUpdateModelAsync
完全
这些都有它们的缺点,所以我希望在这个列表中有第四个我没有看到的条目,因为我很无知。
查看了ControllerBase的源代码后,我注意到问题中的麻烦方法依赖于静态方法ModelBindingHelper.TryUpdateModelAsync
(严重!!!!?
正如你已经痛苦地发现的那样,这使得测试你的控制器有些麻烦。
我在想,也许这个困难告诉了我一些东西
好吧,别再疑惑了。它是。:)
这是你可能忽略的另一个选项。
public interface IModelBindingHelperAdaptor {
Task<bool> TryUpdateModelAsync<TModel>(ControllerBase controller, TModel model) where TModel : class;
}
一个实现可以是这样的
public class DefaultModelBindingHelperAdaptor : IModelBindingHelperAdaptor {
public virtual Task<bool> TryUpdateModelAsync<TModel>(ControllerBase controller, TModel model) where TModel : class {
return controller.TryUpdateModelAsync(model);
}
}
将IModelBindingHelperAdaptor
作为一个依赖项注入到你的控制器中,并让它调用demon衍生方法。
var bindingSuccess = await modelBindingHelper.TryUpdateModelAsync(this, vm);
您现在可以自由地模拟您的抽象,而不需要所有的紧密耦合,这是我认为他们首先应该做的。
现在我假设你已经知道在你的启动中设置必要的东西,以允许上面的建议工作,所以它应该不是一个困难的任务,让它启动并运行