【问题标题】:How to unit test an ASP.NET 5 account controller using ASP.NET Identity 3如何使用 ASP.NET Identity 3 对 ASP.NET 5 帐户控制器进行单元测试
【发布时间】:2016-04-21 08:59:09
【问题描述】:

我想单元测试一个使用 ASP.NET Identity 3 的 ASP.NET 5 帐户控制器,但我不确定执行此操作的最佳方法是什么。我的帐户控制器正在使用 UserManager 并且我可以看到这个 UserManager 类没有我可以用来模拟它的接口,我已经检查了源代码。我认为的一种方法是将它包装到另一个实现接口的类中,然后将其用于模拟。这是使帐户控制器可单元测试的唯一方法还是其他更好的方法。请注意,我指的不是需要使用数据库的集成测试。

【问题讨论】:

    标签: c# asp.net asp.net-mvc unit-testing


    【解决方案1】:

    实际上,有一个Typemock Isolator 工具,它不仅可以模拟接口。您可以模拟和测试几乎任何东西,而无需创建大量的包装器或接口等。

    【讨论】:

      【解决方案2】:

      有两种方法可以做到这一点。

      模拟框架

      UserManager 不是密封类。您可以使用 NSubstitute、Mocks 等现有框架将虚拟 UserManager 注入到您的调用代码中。大多数这些框架(我知道)支持模拟中非密封类的覆盖行为,只要该方法被标记为virtual,UserManager 上的几乎所有这些方法都有。这是一个如何使用 NSubstitute(我选择的框架)的示例。

      var uManager = NSubstitute.Substitute.For<UserManager<MyUserType, int>>();
      var result = new ClaimsIdentity();
      uManager.CreateIdentityAsync(NSubstitute.Arg.Any<MyUserType>(), "login").Returns(Task.FromResult(result));
      var controller = new MyAuthController(uManager);
      controller.DoSomething();
      

      代码重构

      这是一种更复杂的方法,但从长远来看可能更好。

      这是UserManager 的类签名(身份框架的第 2 版,但我想第 3 版对类本身没有任何重大更改,但可能略有不同)。

      public class UserManager<TUser, TKey> : IDisposable where TUser : class, IUser<TKey> where TKey : IEquatable<TKey>
      

      如您所述,该类未实现IUserManager 接口,但未密封,因此您可以创建自己的实现。您的实现可以实现一个接口,该接口可以指定原始UserManager&lt;TUser, TKey&gt; 类上的现有方法,然后您可以使用explicit implementation 实现该接口。

      示例方法签名,然后是您的实现。

      UserManager&lt;TUser, TKey&gt;上的方法

      public virtual Task<ClaimsIdentity> CreateIdentityAsync(TUser user, string authenticationType)
      

      界面上的方法(在本例中为强类型)。

      Task<ClaimsIdentity> CreateIdentityAsync(MyUserType user, string authenticationType);
      

      具体类的实现(在本例中为强类型)。

      async Task<ClaimsIdentity> IMyUserTypeManager.CreateIdentityAsync(MyUserType user, string authenticationType)
      {
          return await this.CreateIdentityAsync(user, authenticationType);
      }
      

      使用您的控制器创建模拟与上面第一个示例中的说明相同。

      这种方法的好处:

      1. 您现在已经更好地从实现代码中抽象出您正在使用 ASP.NET Identity 框架这一事实。这应该使将来更容易更新和/或更改 ASP.NET 标识。
      2. 您现在可以通过调用代码引用接口而不是具体类。这将使单元测试更容易,因为您可以更轻松地为这些接口创建模拟/替代。

      这种方法的缺点是您必须创建和维护身份代码的代理,但通常您实际使用/调用的方法数量相当有限,因此工作量不大。

      【讨论】:

        【解决方案3】:

        这就是我必须做的才能让它工作。我完全抽象了接口背后的身份模型,使其对持久性无知。

        我创建了一些默认类,它们基本上包装了身份模型,使我能够将紧耦合与身份 3 分离,这允许模拟并使我的控​​制器可单元测试。

        【讨论】:

        • 实际上,这只是如何做到这一点。这就是为什么这些测试称为“单元测试”。单元意味着测试单个单元,而不是单元之间的集成。您正在实施的登录是一个单独的单元,身份和身份验证 - 另一个单元。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-12
        • 1970-01-01
        相关资源
        最近更新 更多