繁体   English   中英

模拟单元测试在MVC 5中添加用户身份

[英]Mock Unit Testing Add User Identity in MVC 5

我正在尝试为现有的MVC Web应用程序编写单元测试。 在这种情况下,我遇到了一些问题,例如用户身份和服务调用。

我的基本控制器:

public class BaseController : Controller
{
     public AppUser CurrentUser
    {
        get
        {
            return new AppUser(this.User as ClaimsPrincipal);
        }         
    }
}

调节器

public class NewsController : BaseController
{
    private readonly iNewsService _newsService;
    private readonly IMapper _mapper;

    public NewsController(iNewsService newsService, IMapper mapper)
    {
        _newsService = newsService;
        _mapper = mapper;
    }

    public ActionResult List(int CompanyID == 0)
    {
        var data = _newsService.List(CompanyID, CurrentUser.CompanyType);
        return View();
    }
}    

测试代码:

[TestClass]
public class NewsControllerTest
{
    [TestMethod]
    public void NewsList()
    {
        var mockNewsService = new Mock<iNewsService>();
        var mockMapper = new Mock<IMapper>();

        IList<Claim> claimCollection = new List<Claim>
        {
            new Claim("UserName", "admin"),
            new Claim("CompanyType", "true"),
        };

        var identityMock = new Mock<ClaimsIdentity>();
        identityMock.Setup(x => x.Claims).Returns(claimCollection);

        var cp = new Mock<ClaimsPrincipal>();
        cp.Setup(m => m.HasClaim(It.IsAny<string>(), It.IsAny<string>())).Returns(true);
        cp.Setup(m => m.Identity).Returns(identityMock.Object);


        var contextMock = new Mock<HttpContextBase>();
        contextMock.Setup(ctx => ctx.User).Returns(cp.Object);

        var controllerContextMock = new Mock<ControllerContext>();            
        controllerContextMock.Setup(con => con.HttpContext).Returns(contextMock.Object);
        controllerContextMock.Setup(con => con.HttpContext.User).Returns(cp.Object);

        NewsController controller = new NewsController(mockNewsService.Object, mockMapper.Object);
        controller.ControllerContext = controllerContextMock.Object;

        // Act
        ViewResult result = controller.List(1) as ViewResult;

        // Assert
        Assert.IsNotNull(result);

    }
 }

AppUser类别:

public class AppUser : ClaimsPrincipal
{
    public AppUser(ClaimsPrincipal principal) : base(principal)
    {
    }

    public string Name
    {
        get
        {
            return this.FindFirst("UserName").Value;
        }
    }

    public string CompanyType
    {
        get
        {
            return this.FindFirst("CompanyType").Value;
        }
    }
}

INewsServices:

public interface iNewsService
{
    IEnumerable<Model.News> List(string companyType, string CompanyID);
}

注意:INewsServices是单独的库

这是我的实际代码,但我的CurrentUser为空值始终无法正常工作。 我无法在父控制器的CurrentUser中分配值,有时我的新闻服务也没有调用List方法。

您如何模拟ClaimsPrincipal导致FindFirst返回null并且在调用Value时它会返回NRE。 无需模拟索赔主体,只需为测试创建新实例即可。

[TestClass]
public class NewsControllerTest {
    [TestMethod]
    public void _NewsList() {
        //Arrange           
        var companyId = 1;
        var companyType = "someType";
        var claims = new List<Claim>
        {
            new Claim("UserName", "admin"),
            new Claim("CompanyType", companyType),
        };
        var principal = new ClaimsPrincipal(new ClaimsIdentity(claims));

        var contextMock = new Mock<HttpContextBase>();
        contextMock.Setup(_ => _.User).Returns(principal);

        var fakeNews = new List<News>() { new News(), new News() };
        var mockNewsService = new Mock<INewsService>();
        mockNewsService
            .Setup(_ => _.List(It.IsAny<string>(), It.IsAny<string>())
            .Returns(fakeNews);

        var controller = new NewsController(mockNewsService.Object, Mock.Of<IMapper>());
        controller.ControllerContext = new ControllerContext(contextMock.Object, new RouteData(), controller);

        // Act
        ViewResult result = controller.List(companyId) as ViewResult;

        // Assert
        Assert.IsNotNull(result);
        mockNewsService.Verify(_ => _.List(It.IsAny<string>(), It.IsAny<string>()), Times.AtLeastOnce);
    }
}

您还应该考虑更新AppUser以避免NRE

public class AppUser : ClaimsPrincipal {
    public AppUser(ClaimsPrincipal principal)
        : base(principal) {
    }

    public string Name {
        get {
            return this.FindFirst("UserName")?.Value;
        }
    }

    public string CompanyType {
        get {
            return this.FindFirst("CompanyType")?.Value;
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM