MOQ单元测试失败 - ASP.NET MVC

时间:2016-10-04 23:02:42

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

有人可以帮忙解释为什么会失败吗?我想我可能会跟踪它与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();
}

CONTROLLER

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

REPOSITORY

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

REPOSITORY

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)

        );
    }        
}

1 个答案:

答案 0 :(得分:1)

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

您需要使用虚拟用户帐户设置控制器上下文。这是一个帮助器类,可用于模拟获取用户主体所需的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