【问题标题】:MOQ Unit Test Failing - ASP.NET MVCMOQ 单元测试失败 - ASP.NET MVC
【发布时间】:2016-10-04 23:02:41
【问题描述】:

有人可以帮忙解释为什么会失败吗?我想我可能会将其归结为与 User.Identity.Name 有关。它在“Act”处失败,我得到一个 System.NullReferenceException。但是,同一控制器中的另一种方法确实有效。

工作测试

[TestMethod]
public void Home_Index_Returns_ActionResult()
{
    //Arrange
    var mockRepository1 = new Mock<IEditDataRepository>();
    var mockRepository2 = new Mock<IIdentityRepository>();

     mockRepository1
             .Setup(x => x.Edit(It.IsAny<UTCFormViewModel>(), It.IsAny<string>()));
    HomeController controller = new HomeController(mockRepository1.Object, mockRepository2.Object);

    //Act
    ActionResult result = controller.Index();

    //Assert
    Assert.IsInstanceOfType(result, typeof(ActionResult));
}

不工作测试(在不同的方法上)

[TestMethod]
public void Edit_Method_Test()
{
    //Arrange
    var mockRepository1 = new Mock<IEditDataRepository>();
    var mockRepository2 = new Mock<IIdentityRepository>();

    mockRepository1
         .Setup(x => x.Edit(It.IsAny<UTCFormViewModel>(), It.IsAny<string>()));

    HomeController controller = new HomeController(mockRepository1.Object, mockRepository2.Object);

    //Act (Fails Here)
    controller.Edit(It.IsAny<UTCFormViewModel>());

    //Assert
    mockRepository1.VerifyAll();
    mockRepository2.VerifyAll();
}

控制器

namespace UTC.Controllers
{
    [Authorize]
    public class HomeController : Controller       
    {
        private IEditDataRepository _editDataRepository;
        private IIdentityRepository _identityRepository;

        public HomeController(IEditDataRepository editDataRepository, IIdentityRepository identityRepository )
        {
            _editDataRepository = editDataRepository;
            _identityRepository = identityRepository;
        }

        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "Field1, Field2")] UTCFormViewModel model)
        {
            if (ModelState.IsValid)
            {
                string fullWindowsUser = User.Identity.Name;
                string windowsUser = _identityRepository.GetWindowsUser(fullWindowsUser);

                _editDataRepository.Edit(model, windowsUser);
                return new HttpStatusCodeResult(HttpStatusCode.OK);
            }
            else
            {
                throw new HttpException(400, "ModelState Invalid");
            }
        }
    }    
}

存储库

namespace UTC.Repositories
{
    public class IdentityRepository : IIdentityRepository
    {
        public string GetWindowsUser(string fullWindowsUser)
        {
            //Strip off the domain and lower text
            var windowsUser = fullWindowsUser.ToString().ToLower().Split('\\')[1];

            return windowsUser;
        }
    } 
}

存储库

namespace UTC.Repositories
{
    public class EditDataRepository : IEditDataRepository
    {
        private UTCEntities db = new UTCEntities();

        public void Edit(UTCFormViewModel model, string windowsUser)
        {
            db.ustp_UTCUpdate(windowsUser, model.Field1, model.Field2)

        );
    }        
}

【问题讨论】:

  • 堆栈跟踪说什么?
  • 我刚刚收到这条消息System.NullReferenceException: Object reference not set to an instance of an object.
  • 这是异常的“消息”。该异常还有一个“stacktrace”,它将告诉您它在控制器中发生的确切位置。调试测试以检查它。
  • 您对 User.Identity.Name 的看法是正确的。您需要为控制器设置一个假用户,默认情况下为空,除非在控制器上下文中另外设置
  • 你需要模拟用户。参考答案herehere

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


【解决方案1】:

您正在访问User.Identity.Name,但控制器的User 属性未在您的测试方法中设置,因此访问时它将为空

您需要使用虚拟用户帐户设置控制器上下文。这是一个帮助类,您可以使用它来模拟获取用户主体所需的HttpContext

private class MockHttpContext : HttpContextBase {
    private readonly IPrincipal user;

    public MockHttpContext(string username, string[] roles = null) {
        var identity = new GenericIdentity(username);
        var principal = new GenericPrincipal(identity, roles ?? new string[] { });
        user = principal;
    }

    public override IPrincipal User {
        get {
            return user;
        }
        set {
            base.User = value;
        }
    }
}

在初始化目标控制器后的测试中,您需要设置控制器上下文

//...other code removed for brevity

var controller = new HomeController(mockRepository1.Object, mockRepository2.Object);

controller.ControllerContext = new ControllerContext {
    Controller = controller,
    HttpContext = new MockHttpContext("fakeuser@example.com")
};

//...other code removed for brevity

【讨论】:

  • 非常感谢。我会试一试,让你知道情况如何。但是有一个问题,你会把那个助手类放在哪里?
  • 在测试项目中
  • 效果很好!杰出的!谢谢。
猜你喜欢
  • 2021-04-12
  • 1970-01-01
  • 2011-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-14
相关资源
最近更新 更多