如何在NUnit中传递UserId?

时间:2017-02-21 14:11:12

标签: c# visual-studio unit-testing asp.net-web-api nunit

我有点试图弄清楚如何测试以下内容: 这是GetProjects方法。

[Authorize]
[HttpGet]
[Route("api/UserProject/GetUserProjects")]
public HttpResponseMessage GetProjects()
{
    string userId = User.Identity.GetUserId();
    if (!ModelState.IsValid)
    {
        return new HttpResponseMessage(HttpStatusCode.BadRequest);
    }

    try
    {
        List<ProjectDto> userProjectsDtos = projectBll.GetProjects(userId);
        return Request.CreateResponse(HttpStatusCode.OK, userProjectsDtos);
     }
     catch (Exception)
     {
        return new HttpResponseMessage(HttpStatusCode.InternalServerError);
     }
}

在这里,我尝试为该方法运行NUnit测试。

[TestClass]
public class TestUserProjects
{
    [TestMethod]
    public void GetUserProjectsTest()
    {
        // Arragnge
        var controller = new UserProjectController();
        controller.Request = new HttpRequestMessage();
        controller.Configuration = new HttpConfiguration();

        foreach (var testUserId in GetTestUserIds())
        {
            // Act
            var response = controller.GetProjects();

            // Assert
            List<ProjectDto> projects;
            Assert.IsTrue(response.TryGetContentValue<List<ProjectDto>>(out projects));
            //Assert.AreEqual(5, projects.Count); // Check projects count
            Assert.AreEqual(HttpStatusCode.OK,response.StatusCode);
            Assert.AreEqual(HttpStatusCode.OK, response.StatusCode,"GetUserProjects : id is {0} and count is {1}",testUserId,projects.Count);
            System.Diagnostics.Debug.WriteLine("GetUserProjects : for id {0} ProjectCount = {1}", testUserId, projects.Count);
        }
    }
}

我正在尝试传递 userId ,但不知道在哪里写。

3 个答案:

答案 0 :(得分:1)

它不是“可模仿的”,你应该创建一个不同的函数,它将接收用户名作为参数。

您的WebAPI将调用该函数,您的测试将测试逻辑。

答案 1 :(得分:1)

静态访问会创建在测试期间无法轻易忽略的硬依赖项。

解决方案是将该依赖性从测试中的方法中拉出来。我会这样做,在测试时可以模拟IUserProvider依赖项,并提供适合测试的任何用户ID。

public interface IUserProvider
{
    public string GetUserId();
}

public class UserProvider : IUserProvider
{
    public string GetUserId()
    {
        return User.Identity.GetUserId();
    }
}

public class UserProjectController
{
    private IUserProvider UserProvider { get; set;}

    public UserProjectController(IUserProvider userProvider)
    {
        UserProvider = userProvider;
    }

    [Authorize]
    [HttpGet]
    [Route("api/UserProject/GetUserProjects")]
    public HttpResponseMessage GetProjects()
    {
        string userId = UserProvider.GetUserId();
        if (!ModelState.IsValid)
        {
            return new HttpResponseMessage(HttpStatusCode.BadRequest);
        }

        try
        {
            List<ProjectDto> userProjectsDtos = projectBll.GetProjects(userId);
            return Request.CreateResponse(HttpStatusCode.OK, userProjectsDtos);
         }
         catch (Exception)
         {
            return new HttpResponseMessage(HttpStatusCode.InternalServerError);
         }
    }
}

测试时模拟IUserProvider的语法将随着不同的测试框架而改变。使用Moq看起来像这样

[TestClass]
public class TestUserProjects
{
    [TestMethod]
    public void GetUserProjectsTest()
    {
        // Arrange
        var userProviderMock = new Mock<IUserProvider>();
        userProviderMock.Setup(userProvider => userProvider.GetUserId())
                        .Returns("4e934c03-b02f-47bf-8bdf-e1c98a737cc6");
        var controller = new UserProjectController(userProviderMock.Object);
        controller.Request = new HttpRequestMessage();
        controller.Configuration = new HttpConfiguration();

        foreach (var testUserId in GetTestUserIds())
        {
            // Act
            var response = controller.GetProjects();

            // Assert
            List<ProjectDto> projects;
            Assert.IsTrue(response.TryGetContentValue<List<ProjectDto>>(out projects));
            //Assert.AreEqual(5, projects.Count); // Check projects count
            Assert.AreEqual(HttpStatusCode.OK,response.StatusCode);
            Assert.AreEqual(HttpStatusCode.OK, response.StatusCode,"GetUserProjects : id is {0} and count is {1}",testUserId,projects.Count);
            System.Diagnostics.Debug.WriteLine("GetUserProjects : for id {0} ProjectCount = {1}", testUserId, projects.Count);
        }
    }
}

编辑部分new中的第一行创建了IUserProvider模拟并设置GetUserId()以返回测试用户ID。

答案 2 :(得分:1)

如果要求对请求进行身份验证,则应使用经过身份验证的用户的原则填充User属性。在单元测试期间,框架不会填充此内容。

对于ApiController,您可以在安排单元测试期间设置User属性。然而,GetUserId()扩展方法正在寻找ClaimsIdentity,因此您应该提供一个

[TestClass]
public class TestUserProjects {
    [TestMethod]
    public void GetUserProjectsTest() {
        // Arrange
        var controller = new UserProjectController();
        controller.Request = new HttpRequestMessage();
        controller.Configuration = new HttpConfiguration();

        foreach (var testUserId in GetTestUserIds()) {
            //Arrange specific user
            var identity = new GenericIdentity(testUserId, "");
            identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, testUserId.ToString()));
            identity.AddClaim(new Claim(ClaimTypes.Name, testUserId.ToString()));

            var principal = new GenericPrincipal(identity, roles: new string[] { });
            var user = new ClaimsPrincipal(principal);

            controller.User = user;

            // Act
            var response = controller.GetProjects();

            // Assert
            List<ProjectDto> projects;
            Assert.IsTrue(response.TryGetContentValue<List<ProjectDto>>(out projects));
            //Assert.AreEqual(5, projects.Count); // Check projects count
            Assert.AreEqual(HttpStatusCode.OK,response.StatusCode);
            Assert.AreEqual(HttpStatusCode.OK, response.StatusCode,"GetUserProjects : id is {0} and count is {1}",testUserId,projects.Count);
            System.Diagnostics.Debug.WriteLine("GetUserProjects : for id {0} ProjectCount = {1}", testUserId, projects.Count);
        }
    }
}