42

我正在使用 Unit Test for ASP.NET Web API 编写测试用例。

现在我有一个动作,它调用了我在服务层中定义的一些方法,我在其中使用了以下代码行。

string username = User.Identity.Name;
// do something with username
// return something

现在如何为此创建单元测试方法,我得到空引用异常。我对编写单元测试和东西有点陌生。

我只想为此使用单元测试。请帮我解决这个问题。

4

8 回答 8

47

下面的只是这样做的一种方法:

public class FooController : ApiController {

    public string Get() {

        return User.Identity.Name;
    }
}

public class FooTest {

    [Fact]
    public void Foo() {

        var identity = new GenericIdentity("tugberk");
        Thread.CurrentPrincipal = new GenericPrincipal(identity, null);
        var controller = new FooController();

        Assert.Equal(controller.Get(), identity.Name);
    }
}
于 2012-10-08T12:45:37.777 回答
17

这是我在NerdDinner测试教程中找到的另一种方法。它适用于我的情况:

DinnersController CreateDinnersControllerAs(string userName)
{

    var mock = new Mock<ControllerContext>();
    mock.SetupGet(p => p.HttpContext.User.Identity.Name).Returns(userName);
    mock.SetupGet(p => p.HttpContext.Request.IsAuthenticated).Returns(true);

    var controller = CreateDinnersController();
    controller.ControllerContext = mock.Object;

    return controller;
}

[TestMethod]
public void EditAction_Should_Return_EditView_When_ValidOwner()
{

    // Arrange
    var controller = CreateDinnersControllerAs("SomeUser");

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

    // Assert
    Assert.IsInstanceOfType(result.ViewData.Model, typeof(DinnerFormViewModel));
}

请务必阅读完整部分:模拟 User.Identity.Name 属性

它使用Moq您可以在Test project使用 NuGet 时安装的模拟框架:http: //nuget.org/packages/moq

于 2012-11-03T18:00:47.960 回答
11

对于 WebApi 5.0,这略有不同。您现在可以执行以下操作:

controller.User = new ClaimsPrincipal(
  new GenericPrincipal(new GenericIdentity("user"), null));
于 2013-09-17T18:43:39.767 回答
1

这些都对我不起作用,我在另一个问题上使用了解决方案,该问题使用 Moq 在 ControllerContext 中设置用户名:https ://stackoverflow.com/a/6752924/347455

于 2014-09-03T15:39:24.240 回答
1

这是我的解决方案。

var claims = new List<Claim>
{
    new Claim(ClaimTypes.Name, "Nikita"),
    new Claim(ClaimTypes.NameIdentifier, "1")
};

var identity = new ClaimsIdentity(claims);
IPrincipal user = new ClaimsPrincipal(identity);

controller.User = user;
于 2017-12-08T08:57:26.477 回答
0

在这里,我找到了另一种方法的解决方案,即如何从测试方法设置控制器级别测试的用户身份名称。

public static void SetUserIdentityName(string userId)
        {
            IPrincipal principal = null;
            principal = new GenericPrincipal(new GenericIdentity(userId), 
            new string[0]);
            Thread.CurrentPrincipal = principal;
            if (HttpContext.Current != null)
            {
                HttpContext.Current.User = principal;
            }
        }
于 2014-04-01T12:28:58.223 回答
0

如果您有很多控制器要测试,那么我建议创建一个基类并在构造函数中创建一个GenericIdentity&GenericPrincipal并设置Thread.CurrentPrincipal

GenericPrincipal principal = new GenericPrincipal(new 
    GenericIdentity("UserName"),null); Thread.CurrentPrincipal = principal; 

然后继承那个类..这样每个单元测试类都会有原理对象集

[TestClass]
public class BaseUnitTest
{
    public BaseUnitTest()
    {
      GenericPrincipal principal = new GenericPrincipal(new GenericIdentity("UserName"),null);   
      Thread.CurrentPrincipal = principal;
    }
}


[TestClass]
public class AdminUnitTest : BaseUnitTest
{
   [TestMethod]
   public void Admin_Application_GetAppliction()
   {
   }
}
于 2014-05-15T03:03:32.710 回答
0

当我运行单元测试时 - 在我的情况下,它使用 Windows 身份验证,Identity.Name 是我的域名,我也想为测试更改它。所以我在 IAuthenticationFilter 中使用这种方法来“破解”我想要的东西

于 2017-08-11T08:45:34.223 回答