【问题标题】:How do I mock the ApplicationUserManager for unit testing using nsubstitute and nunit如何使用 nsubstitute 和 nunit 模拟 ApplicationUserManager 进行单元测试
【发布时间】:2015-01-21 10:42:17
【问题描述】:

我在使用 nsubstitute 和 nunit 模拟 ApplicationUserManager 类以测试我的操作方法时遇到问题。这是我嘲笑班级的方式。

var _userManager = Substitute.For<ApplicationUserManager>();

在我的测试系统中,我正在使用构造函数注入来注入类。当我运行测试时,我收到此错误消息。

Castle.DynamicProxy.InvalidProxyConstructorArgumentsException : Can not instantiate proxy of class: JobHub.Web.Identity.ApplicationUserManager.
Could not find a parameterless constructor.

我的问题是如何像使用类的 SetPhoneNumberAsync()method 一样使用 NSubstitue 正确模拟这个类。

编辑 顺便说一句,这是我要测试的一段代码

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create(UserProfileView model)
{
    if (ModelState.IsValid)
    {
        var userId = User.Identity.GetUserId(); 

        var profile = model.MapToProfile(userId);

        if (CommonHelper.IsNumerics(model.PhoneNo))
        {
            await _userManager.SetPhoneNumberAsync(userId, model.PhoneNo);
        }

        if (model.ProfileImage != null)
        {
            profile.ProfileImageUrl = await _imageService.SaveImage(model.ProfileImage);
        }

        _profileService.AddProfile(profile);
        _unitofWork.SaveChanges();

        //Redirect to the next page (i.e: setup experiences)
        return RedirectToAction("Skills", "Setup");
    }
    return View("UserProfile", model);
}

【问题讨论】:

    标签: asp.net-mvc-5 nunit nsubstitute


    【解决方案1】:

    substituting for a concrete class 时出现此错误,但未提供所需的构造函数参数。如果MyClass 构造函数有两个参数,则可以这样替换:

    var sub = Substitute.For<MyClass>(firstArg, secondArg);
    

    请记住,NSubstitute 不能与非虚拟方法一起使用,并且在替换类(而不是接口)时,在某些情况下可以执行真实代码。

    Creating a substitute 对此进行了进一步解释。

    【讨论】:

    • 是的,但是我怎样才能创建一个不执行真实代码而是只调用传递给它的回调的真实类的替代品。我尝试使用when-do callbacks,虽然它调用了回调,但它仍然调用了真正的代码。如果没有,可以用起订量来实现吗?
    • 构造函数代码和非虚拟成员中的代码将始终运行。我相信 Moq、FakeItEasy 和 RhinoMocks 有类似的限制,尽管值得检查这些项目和/或向 SO 发布一般的 .net 模拟问题。确保真实代码不会运行的最佳方法是使用接口(因为它们没有真实代码)。如果您无法编辑原始类,一种选择是使用适配器模式使原始类符合接口。
    • 非常感谢,通过使用 Moq 扩展方法模拟 IUserStore&lt;Account&gt;IUserPhoneNumberStore&lt;Account&gt; 并返回所需的 Task&lt;IdentityResult&gt;,我终于解决了问题并通过了测试。虽然看起来有点乱,但确实有效。
    猜你喜欢
    • 2018-10-20
    • 1970-01-01
    • 1970-01-01
    • 2019-04-17
    • 2021-12-03
    • 2011-02-20
    • 1970-01-01
    • 1970-01-01
    • 2021-01-09
    相关资源
    最近更新 更多