在ASP.NETWeb API中为使用User.Identity.Name的方法编写单元测试

dzhpxtsq  于 2023-10-21  发布在  .NET
关注(0)|答案(9)|浏览(160)

我正在使用ASP.NET Web API的单元测试编写测试用例。
现在我有了一个动作,它调用了我在服务层中定义的某个方法,我在其中使用了以下代码行。

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

现在我如何创建单元测试方法,我得到空引用异常。我对编写单元测试之类的东西还比较陌生。
我只想使用单元测试来实现这一点。请帮我这个忙。

a0x5cqrl

a0x5cqrl1#

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

  1. public class FooController : ApiController {
  2. public string Get() {
  3. return User.Identity.Name;
  4. }
  5. }
  6. public class FooTest {
  7. [Fact]
  8. public void Foo() {
  9. var identity = new GenericIdentity("tugberk");
  10. Thread.CurrentPrincipal = new GenericPrincipal(identity, null);
  11. var controller = new FooController();
  12. Assert.Equal(controller.Get(), identity.Name);
  13. }
  14. }
展开查看全部
xpszyzbs

xpszyzbs2#

下面是我在NerdDinner测试教程中发现的另一种方法。它在我的情况下工作:

  1. DinnersController CreateDinnersControllerAs(string userName)
  2. {
  3. var mock = new Mock<ControllerContext>();
  4. mock.SetupGet(p => p.HttpContext.User.Identity.Name).Returns(userName);
  5. mock.SetupGet(p => p.HttpContext.Request.IsAuthenticated).Returns(true);
  6. var controller = CreateDinnersController();
  7. controller.ControllerContext = mock.Object;
  8. return controller;
  9. }
  10. [TestMethod]
  11. public void EditAction_Should_Return_EditView_When_ValidOwner()
  12. {
  13. // Arrange
  14. var controller = CreateDinnersControllerAs("SomeUser");
  15. // Act
  16. var result = controller.Edit(1) as ViewResult;
  17. // Assert
  18. Assert.IsInstanceOfType(result.ViewData.Model, typeof(DinnerFormViewModel));
  19. }

请确保您阅读完整部分:Mocking the User.Identity.Name property
它使用Moq mocking框架,您可以使用NuGet安装在Test project中:http://nuget.org/packages/moq

展开查看全部
tjvv9vkg

tjvv9vkg3#

在WebApi 5.0中,这一点略有不同。您现在可以:

  1. controller.User = new ClaimsPrincipal(
  2. new GenericPrincipal(new GenericIdentity("user"), null));
vxbzzdmp

vxbzzdmp4#

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

uyto3xhc

uyto3xhc5#

这是我的解决方案。

  1. var claims = new List<Claim>
  2. {
  3. new Claim(ClaimTypes.Name, "Nikita"),
  4. new Claim(ClaimTypes.NameIdentifier, "1")
  5. };
  6. var identity = new ClaimsIdentity(claims);
  7. IPrincipal user = new ClaimsPrincipal(identity);
  8. controller.User = user;
ru9i0ody

ru9i0ody6#

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

  1. public static void SetUserIdentityName(string userId)
  2. {
  3. IPrincipal principal = null;
  4. principal = new GenericPrincipal(new GenericIdentity(userId),
  5. new string[0]);
  6. Thread.CurrentPrincipal = principal;
  7. if (HttpContext.Current != null)
  8. {
  9. HttpContext.Current.User = principal;
  10. }
  11. }
r55awzrz

r55awzrz7#

当我运行单元测试时-在我的情况下,它使用Windows身份验证和Identity。Name是我的域名,我也想为测试更改。所以我用such approach with 'hacking' things I want in IAuthenticationFilter

dl5txlt9

dl5txlt98#

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

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

继承这个类。这样,每个单元测试类都将具有Principle对象集

  1. [TestClass]
  2. public class BaseUnitTest
  3. {
  4. public BaseUnitTest()
  5. {
  6. GenericPrincipal principal = new GenericPrincipal(new GenericIdentity("UserName"),null);
  7. Thread.CurrentPrincipal = principal;
  8. }
  9. }
  10. [TestClass]
  11. public class AdminUnitTest : BaseUnitTest
  12. {
  13. [TestMethod]
  14. public void Admin_Application_GetAppliction()
  15. {
  16. }
  17. }
展开查看全部
50few1ms

50few1ms9#

不知道AspNetCore是否改变了很多,但现在在Net7中,你可以简单地做到这一点

  1. someController.ControllerContext.HttpContext = new DefaultHttpContext
  2. {
  3. User = new GenericPrincipal(new GenericIdentity(userName) , new []{string.Empty})
  4. };

一个工作单元测试的例子

  1. [Test]
  2. public async Task GetAll_WhenUserNotExist_ReturnsNotFound()
  3. {
  4. // arrange
  5. var autoMock = AutoMock.GetLoose();
  6. const string userName = "[email protected]";
  7. var customersServiceMock = autoMock.Mock<ICustomerService>();
  8. customersServiceMock
  9. .Setup(service => service.GetAll(userName)).Throws<UserDoesNotExistException>();
  10. var customerController = autoMock.Create<CustomerController>();
  11. //
  12. // Create a new DefaultHttpContext and assign a generic identity which you can give a user name
  13. customerController.ControllerContext.HttpContext = new DefaultHttpContext
  14. {
  15. User = new GenericPrincipal(new GenericIdentity(userName) , new []{string.Empty})
  16. };
  17. var httpResult = await customerController.GetAllCustomers() as NotFoundResult;
  18. // act
  19. Assert.IsNotNull(httpResult);
  20. }

控制器的实现

  1. [HttpGet]
  2. [Route("all")]
  3. public async Task<IActionResult> GetAllCustomers()
  4. {
  5. // User identity name will return harry@potter now.
  6. var userName = User.Identity?.Name;
  7. try
  8. {
  9. var customers = await _customerService.GetAll(userName).ConfigureAwait(false);
  10. return Ok(customers);
  11. }
  12. catch (UserDoesNotExistException)
  13. {
  14. Log.Warn($"User {userName} does not exist");
  15. return NotFound();
  16. }
  17. }
展开查看全部

相关问题