C# 如何在NUnit中传递用户ID?

C# 如何在NUnit中传递用户ID?,c#,visual-studio,unit-testing,asp.net-web-api,nunit,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 Htt

我有点挠头,想弄清楚如何测试以下内容: 这里是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);
     }
}
[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);
        }
    }
}
[授权]
[HttpGet]
[路由(“api/UserProject/GetUserProjects”)]
公共HttpResponseMessage GetProjects()
{
字符串userId=User.Identity.GetUserId();
如果(!ModelState.IsValid)
{
返回新的HttpResponseMessage(HttpStatusCode.BadRequest);
}
尝试
{
List userProjectsDtos=projectBll.GetProjects(userId);
return Request.CreateResponse(HttpStatusCode.OK,userProjectsDtos);
}
捕获(例外)
{
返回新的HttpResponseMessage(HttpStatusCode.InternalServerError);
}
}
在这里,我尝试对该方法运行NUnit测试。

[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);
     }
}
[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);
        }
    }
}
[TestClass]
公共类TestUserProject
{
[测试方法]
public void GetUserProjectsTest()
{
//排列
var controller=new UserProjectController();
controller.Request=new-HttpRequestMessage();
controller.Configuration=新的HttpConfiguration();
foreach(getTestUserId()中的var testUserId)
{
//表演
var response=controller.GetProjects();
//断言
列出项目清单;
Assert.IsTrue(response.TryGetContentValue(out项目));
//Assert.AreEqual(5,projects.Count);//检查项目计数
AreEqual(HttpStatusCode.OK,response.StatusCode);
AreEqual(HttpStatusCode.OK,response.StatusCode,“GetUserProjects:id为{0},count为{1}”,testUserId,projects.count);
System.Diagnostics.Debug.WriteLine(“GetUserProjects:for id{0}ProjectCount={1}”,testUserId,projects.Count);
}
}
}
我试图传递用户ID,但不知道在哪里写

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


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

静态访问会创建硬依赖项,这些依赖项在测试期间不容易被忽略

解决方案是从被测试的方法中提取依赖关系。我会这样做,以便在测试时模拟
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);
         }
    }
}
公共接口提供程序
{
公共字符串GetUserId();
}
公共类UserProvider:IUserProvider
{
公共字符串GetUserId()
{
返回User.Identity.GetUserId();
}
}
公共类UserProjectController
{
专用IUserProvider UserProvider{get;set;}
公共用户项目控制器(IUserProvider userProvider)
{
UserProvider=UserProvider;
}
[授权]
[HttpGet]
[路由(“api/UserProject/GetUserProjects”)]
公共HttpResponseMessage GetProjects()
{
字符串userId=UserProvider.GetUserId();
如果(!ModelState.IsValid)
{
返回新的HttpResponseMessage(HttpStatusCode.BadRequest);
}
尝试
{
List userProjectsDtos=projectBll.GetProjects(userId);
return Request.CreateResponse(HttpStatusCode.OK,userProjectsDtos);
}
捕获(例外)
{
返回新的HttpResponseMessage(HttpStatusCode.InternalServerError);
}
}
}
测试时模拟IUserProvider的语法将随不同的测试框架而变化。使用它看起来像这样

[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);
        }
    }
}
[TestClass]
公共类TestUserProject
{
[测试方法]
public void GetUserProjectsTest()
{
//安排
var userProviderMock=new Mock();
userProviderLock.Setup(userProvider=>userProvider.GetUserId())
.返回(“4e934c03-b02f-47bf-8bdf-e1c98a737cc6”);
var controller=新的UserProjectController(userProviderMock.Object);
controller.Request=new-HttpRequestMessage();
controller.Configuration=新的HttpConfiguration();
foreach(getTestUserId()中的var testUserId)
{
//表演
var response=controller.GetProjects();
//断言
列出项目清单;
Assert.IsTrue(response.TryGetContentValue(out项目));
//Assert.AreEqual(5,projects.Count);//检查项目计数
AreEqual(HttpStatusCode.OK,response.StatusCode);
AreEqual(HttpStatusCode.OK,response.StatusCode,“GetUserProjects:id为{0},count为{1}”,testUserId,projects.count);
System.Diagnostics.Debug.WriteLine(“GetUserProjects:for id{0}ProjectCount={1}”,testUserId,projects.Count);
}
}
}

新排列部分的第一行创建一个模拟的
IUserProvider
和setup
GetUserId()
以返回一个测试用户id。

如果假设请求经过身份验证,那么
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);
        }
    }
}
[TestClass]
公共类TestUserProject{
[测试方法]
public void GetUserProjectsTest(){
//安排
var controller=new UserProjectController();
controller.Request=new-HttpRequestMessage();
controller.Configuration=新的HttpConfiguration();
foreach(getTestUserId()中的var testUserId){
//安排特定用户
var标识=新的GenericEntity(testUserId,“”);
AddClaim(新声明(ClaimTypes.NameIdentifier,testUserId.ToString());
AddClaim(新声明(ClaimTypes.Name,testUserId.ToString());