Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用TryUpdateModel时asp.net核心mvc控制器单元测试_C#_Unit Testing_Asp.net Core_Asp.net Core Mvc - Fatal编程技术网

C# 使用TryUpdateModel时asp.net核心mvc控制器单元测试

C# 使用TryUpdateModel时asp.net核心mvc控制器单元测试,c#,unit-testing,asp.net-core,asp.net-core-mvc,C#,Unit Testing,Asp.net Core,Asp.net Core Mvc,在asp.net核心应用程序中,我有一对响应编辑操作的控制器方法。一个用于GET,它为实体id接受一个字符串参数: public async Task<IActionResult> Edit(string id) 这很好 现在,我正试图为此编写一个测试,但我发现tryupdatemodelsync需要从HttpContext中获得很多东西,并且需要充实控制器。我已经尝试过模仿这些,但是在查看了tryupdatemodelsync的源代码之后,我意识到我基本上需要模仿所有内容,直到元

在asp.net核心应用程序中,我有一对响应编辑操作的控制器方法。一个用于GET,它为实体id接受一个字符串参数:

public async Task<IActionResult> Edit(string id)
这很好

现在,我正试图为此编写一个测试,但我发现
tryupdatemodelsync
需要从
HttpContext
中获得很多东西,并且需要充实控制器。我已经尝试过模仿这些,但是在查看了
tryupdatemodelsync
的源代码之后,我意识到我基本上需要模仿所有内容,直到元数据,这并不简单

我想知道这个困难是否告诉了我一些事情:
tryupdatemodelsync
使测试变得困难,所以我应该重构控制器方法,使其不依赖于这个助手。相反,我可以为viewmodel的方法添加另一个参数,并用
[FromBody]
对其进行修饰,这样模型绑定将在post字段出现时发生,但在测试时我可以传入视图模型。但是,我喜欢
tryupdatemodelsync
方法,因为它可以将post字段合并到我的视图模型中。我认为实现合并的另一种方法是编写自己的合并方法。好的,没什么大不了的,但是我不想对每个实体都这样做(或者重新发明轮子来编写基于反射的合并),而且真的,我想知道我是否错过了如何编写针对此的单元测试的机会。我可以启动一个完整的
TestServer
,就像我为集成测试所做的那样,但我不确定这是正确的方向,我觉得这会使我的单元测试进一步复杂化。然而,在这种情况下,这可能是合理的吗

我已经看到了以前版本的.net mvc的答案,他们所需要做的只是模拟一个
IValueProvider
,并将其连接到控制器,但在.net core中,
tryupdatemodelsync
似乎已被修改,需要更多移动部件

总而言之,我认为有三种选择:

  • 继续嘲弄和剔除所有可能的碎片
    tryupdatemodelsync
    需要。看来这可能是一条死胡同 到目前为止
  • 使用
    TestServer
    从一点开始进行此测试 使用
    HttpClient
  • 重构此方法以使用
    [FromBody]
    在视图模型参数上,然后编写我自己的合并 每个实体的方法,按单步执行
    tryupdatemodelsync

  • 这些都有其缺点,所以我希望这个列表中有第四个条目我看不到,因为我不知道。

    在查看ControllerBase的源代码后,我注意到有问题的方法依赖于static方法
    ModelBindingHelper.tryupdatemodelsync
    (说真的!!!!?我还以为我们现在进化得更快了呢。)

    正如您已经痛苦地发现的那样,这使得测试您的控制器有些麻烦

    我想知道这个困难是否告诉了我一些事情

    好吧,别再疑惑了。是的

    这里是另一个选项,你可能已经看得太多了。抽象/适应困难,使之回到它产生的深处

    public interface IModelBindingHelperAdaptor {
        Task<bool> TryUpdateModelAsync<TModel>(ControllerBase controller, TModel model) where TModel : class;
    }
    
    您现在可以自由地模拟您的抽象,而无需所有的紧密耦合,这是我认为他们首先应该做的


    现在,我假设您已经知道如何在启动中设置必要的内容,以允许上述建议发挥作用,因此启动并运行该建议对您来说应该不是一项困难的任务。

    查看ControllerBase的源代码后,我注意到有问题的麻烦方法依赖于static方法
    ModelBindingHelper.tryupdatemodelsync
    (说真的!!!!?我还以为我们现在进化得更多呢。)

    正如您已经痛苦地发现的那样,这使得测试您的控制器有些麻烦

    我想知道这个困难是否告诉了我一些事情

    我们别再疑惑了。它是……)

    这里是另一个选项,你可能已经看得太多了。抽象/适应困难,使之回到它产生的深处

    public interface IModelBindingHelperAdaptor {
        Task<bool> TryUpdateModelAsync<TModel>(ControllerBase controller, TModel model) where TModel : class;
    }
    
    您现在可以自由地模拟您的抽象,而无需所有的紧密耦合,这是我认为他们首先应该做的


    现在,我假设您已经知道如何在初创公司中设置必要的东西,以使上述建议发挥作用,因此对您来说,启动并运行它应该不是一项困难的任务。

    好吧,我喜欢这个解决方案-如果您需要模拟它,请将其包装并注入。我同意,ControllerBase没有很好地遵循显式依赖原则。我走了另一个方向,充实了HttpContext,遇到了一个问题,它没有抛出异常,但是模型没有更新。我将把这个留给另一个不同的问题。这似乎提供了一个可行的第四种选择:)好吧,我喜欢这个解决方案——如果您需要模拟它,请将其包装并注入。我同意,ControllerBase没有很好地遵循显式依赖原则。我走了另一个方向,充实了HttpContext,遇到了一个问题,它没有抛出异常,但是模型没有更新。我将把这个留给另一个不同的问题。这似乎提供了一个可行的第四种选择:)
    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);
        }
    }
    
    var bindingSuccess = await modelBindingHelper.TryUpdateModelAsync(this, vm);