我正在使用 Unit Test for ASP.NET Web API 编写测试用例。
现在我有一个动作,它调用了我在服务层中定义的一些方法,我在其中使用了以下代码行。
string username = User.Identity.Name;
// do something with username
// return something
现在如何为此创建单元测试方法,我得到空引用异常。我对编写单元测试和东西有点陌生。
我只想为此使用单元测试。请帮我解决这个问题。
我正在使用 Unit Test for ASP.NET Web API 编写测试用例。
现在我有一个动作,它调用了我在服务层中定义的一些方法,我在其中使用了以下代码行。
string username = User.Identity.Name;
// do something with username
// return something
现在如何为此创建单元测试方法,我得到空引用异常。我对编写单元测试和东西有点陌生。
我只想为此使用单元测试。请帮我解决这个问题。
下面的只是这样做的一种方法:
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);
}
}
这是我在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
对于 WebApi 5.0,这略有不同。您现在可以执行以下操作:
controller.User = new ClaimsPrincipal(
new GenericPrincipal(new GenericIdentity("user"), null));
这些都对我不起作用,我在另一个问题上使用了解决方案,该问题使用 Moq 在 ControllerContext 中设置用户名:https ://stackoverflow.com/a/6752924/347455
这是我的解决方案。
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;
在这里,我找到了另一种方法的解决方案,即如何从测试方法设置控制器级别测试的用户身份名称。
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;
}
}
如果您有很多控制器要测试,那么我建议创建一个基类并在构造函数中创建一个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()
{
}
}
当我运行单元测试时 - 在我的情况下,它使用 Windows 身份验证,Identity.Name 是我的域名,我也想为测试更改它。所以我在 IAuthenticationFilter 中使用这种方法来“破解”我想要的东西