【问题标题】:Unit testing controllers using UserManager.FindById使用 UserManager.FindById 对控制器进行单元测试
【发布时间】:2017-04-26 14:45:30
【问题描述】:

我是对 .net 应用程序进行单元测试的新手,对于我想象的一个非常简单的案例有困难。

// GET: Entities
public ViewResult Index()
{
  _User = UserManager.FindById(User.Identity.GetUserId());
  return View(entityRepository.GetEntities(_User.entityId));         
}

我想测试是否输出了正确的视图,但无法越过用户行。在其他语言中,我会简单地模拟 UserManager.FindById 以始终返回一些预定义的对象,但我无法让它工作。

一直在尝试遵循example mocking the IUserStore 此处给出的方法,但无法使其与我的示例一起使用。为了模拟 FindByNameAsync 他们使用了 store.As

我们将不胜感激地接受任何建议。

我的尝试是采用与上面链接中类似的方法。显然 IUserPasswordStore 是错误的接口,但我不确定如何找到正确的接口。

 var store = new Mock<IUserStore<ApplicationUser>>(MockBehavior.Strict);
 store.As<IUserPasswordStore<ApplicationUser>>()
      .Setup(x => x.FindById(It.IsAny<string>()))
      .Returns(ApplicationUser)null);   

 EntitiesController controller = new EntitiesController();
 var result = controller.Index() as ViewResult;
 Assert.AreEqual("Index", result.ViewName);

【问题讨论】:

  • 如果没有看到您当前的嘲笑UserManager 的尝试,就无法回答这个问题
  • 嗨@haim770 上面已编辑。我最初没有包括它,因为我认为我没有接近答案。谢谢
  • 您不应该将store.Object 作为参数传递给EntitiesController 的构造函数(然后将其分配给this.UserManager)吗?
  • @mwuk,我通过在我控制的接口后面抽象 UserManager 解决了这个问题,并通过构造函数将其作为对我的控制器的依赖项注入。实现类只是简单地包装/改编了实际的 UserManager 类。这样我就可以在单元测试时模拟实现
  • @mwuk 您链接到的示例有答案。您需要遵循该示例。注意他们是如何注入用户管理器的。如果您在本地创建管理器,则无法注入模拟。

标签: asp.net-mvc unit-testing moq


【解决方案1】:

所以,感谢@Nkosi 和@haim770 的指导,我想我有答案了。不过,它似乎仍然过于复杂,所以如果你知道如何简化,我很想听听。

首先需要编写更多可测试的代码,我安装了 Unity 并开始注入依赖项,以便我模拟它们。

通过的解决方案是:

Mock<IPrincipal> mockPrincipal;
string username = "test@test.com";

[TestInitialize]
public void TestInitialize()
{
    //Arrange                
    var identity = new GenericIdentity(username, "");
    var nameIdentifierClaim = new Claim(ClaimTypes.NameIdentifier, username);
    identity.AddClaim(nameIdentifierClaim);

    mockPrincipal = new Mock<IPrincipal>();
    mockPrincipal.Setup(x => x.Identity).Returns(identity);
    mockPrincipal.Setup(x => x.IsInRole(It.IsAny<string>())).Returns(true);
}

[TestMethod]
public void EntitiesIndexDisplaysTheDefaultView()
{
    var context = new Mock<HttpContextBase>(); 
    var principal = mockPrincipal.Object;
    context.Setup(x => x.User).Returns(principal);

    var userManagerMock = new Mock<IUserStore<ApplicationUser>>(MockBehavior.Strict);
    userManagerMock.As<IUserPasswordStore<ApplicationUser>>()
         .Setup(x => x.FindByIdAsync(It.IsAny<string>()))
         .ReturnsAsync(new ApplicationUser() { entityId = "id" });

    var entitiesRepositoryMock = new Mock<IEntityRepository>();
    entitiesRepositoryMock
        .Setup(x => x.GetEntities(It.IsAny<string>()))
        .Returns((IEnumerable<Entity>)new List<Entity>());


    EntitiesController controller = new EntitiesController(new UserManager<ApplicationUser>(userManagerMock.Object), 
                                                               entitiesRepositoryMock.Object);

    controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);
    var result = controller.Index() as ViewResult;
    Assert.AreEqual("", result.ViewName);           
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-01
    • 2019-12-31
    • 2013-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-12
    • 2020-08-27
    相关资源
    最近更新 更多