如何模拟ApplicationUserManager使用nsubstitute和nunit进行单元测试

问题描述:

我在使用nsubstitute和nunit模拟ApplicationUserManager类来测试我的动作方法时遇到问题。这是嘲笑课堂的方式。如何模拟ApplicationUserManager使用nsubstitute和nunit进行单元测试

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

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

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

我的问题是如何正确使用嘲弄作为NSubstitue现在用的是类的SetPhoneNumberAsync()方法这个类。

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

[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); 
     } 

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

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

请记住,NSubstitute不能与非虚拟方法的工作,并为班代时(而不是接口),也有一些真正的代码可以执行的场合。

这在Creating a substitute中有进一步的解释。

+0

是的,但我怎么能创建一个真正的类,不执行真正的代码,而是只调用传递给它的回调的替代品。我尝试过使用[when-do回调](http://nsubstitute.github.io/help/callbacks),尽管它调用了回调函数,但它仍然调用真正的代码。如果没有,可以用moq来实现吗? – Cizaphil 2015-01-22 09:45:09

+0

非虚拟成员中的构造函数代码和代码将始终运行。我相信Moq,FakeItEasy和RhinoMocks都有类似的限制,尽管这些项目值得检查和/或向SO发布一般性的.net模拟问题。确保真正的代码不会运行的最好方法是使用一个接口(因为它们没有真正的代码)。如果您无法编辑原始类,则有一种选择是使用适配器模式使原始类符合接口。 – 2015-01-22 11:10:05

+0

非常感谢,我终于解决了这个问题,并通过使用Moq扩展方法嘲笑'IUserStore '和'IUserPhoneNumberStore ',并返回所需的'Task '来通过测试。虽然看起来有点乱,但它的工作原理。 – Cizaphil 2015-01-22 12:39:58