模拟ApplicationUserManager在ASP中的单元测试.. NET Web Api

本文关键字:单元测试 NET Web Api ApplicationUserManager ASP 模拟 | 更新日期: 2023-09-27 18:12:38

我有以下控制器(WebApi):

[Authorize]
[RoutePrefix("customers/{custId:guid}/carts")]
public class CartsController : BaseApiController
{
    private IUnitOfWork unitOfWork;
    public CartsController(IUnitOfWork unitOfWork)
    {
        this.unitOfWork = unitOfWork;
    }
    [HttpGet]
    [Route("", Name = "GetCart")]
    [ResponseType(typeof(CartReturnModel))]
    public async Task<IHttpActionResult> GetCartAsync([FromUri] Guid custId)
    {
        if (User.Identity != null)
        {
            if (User.Identity.IsAuthenticated)
            {
                var user = await this.AppUserManager.FindByNameAsync(User.Identity.Name);
                if (user != null)
                {
                    // restrict access to self and account admins
                    if (user.Customer_Id == custId || User.IsInRole("system_admin") || User.IsInRole("accounts_author") || User.IsInRole("accounts_reviewer"))
                    {
                        var tmr = new System.Diagnostics.Stopwatch();
                        tmr.Start();
                        var cust = await unitOfWork.Customers.GetCustomerByShippingAddress(custId);
                        if (cust != null)
                        {
                            var cart = await unitOfWork.CartItems.GetCustomerCart(cust);
                            tmr.Stop();
                            System.Diagnostics.Debug.WriteLine("GetCartAsync took " + tmr.ElapsedMilliseconds + " ms");
                            return Ok(this.TheModelFactory.Create(cust, cart.ToList()));
                        }
                        return NotFound();
                    }
                    return Unauthorized();
                }
            }
        }
        return NotFound();
    }
}
}

这个控制器派生自一个基本控制器:

public class BaseApiController : ApiController
{
    public BaseApiController()
    {
    }
    private ModelFactory _modelFactory;
    protected ModelFactory TheModelFactory
    {
        get
        {
            if (_modelFactory == null)
            {
                _modelFactory = new ModelFactory(this.Request, this.AppUserManager);
            }
            return _modelFactory;
        }
    }
    private ApplicationUserManager _AppUserManager = null;
    protected ApplicationUserManager AppUserManager
    {
        get
        {
            return _AppUserManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
        }
    }
    private ApplicationRoleManager _AppRoleManager = null;
    protected ApplicationRoleManager AppRoleManager
    {
        get
        {
            return _AppRoleManager ?? Request.GetOwinContext().GetUserManager<ApplicationRoleManager>();
        }
    }

    protected IHttpActionResult GetErrorResult(IdentityResult result)
    {
        if (result == null)
        {
            return InternalServerError();
        }
        if (!result.Succeeded)
        {
            if (result.Errors != null)
            {
                foreach (string error in result.Errors)
                {
                    ModelState.AddModelError("", error);
                }
            }
            if (ModelState.IsValid)
            {
                // No ModelState errors are available to send, so just return an empty BadRequest.
                return BadRequest();
            }
            return BadRequest(ModelState);
        }
        return null;
    }
}

在过去的一周,我一直在尝试单元测试控制器方法GetCartAsync。但是它总是返回Assert。IsNotNull失败了,我不明白为什么。下面是测试:

 [TestMethod]
public async Task GetCart() {
    {
        IList<CartItem> cart = new List<CartItem>()
        {
            new CartItem
                {
                    Id = Guid.Parse("f1f1f790-1d13-4416-b079-5f41bcedc4ab")
                },
                new CartItem
                {
                    Id = Guid.Parse("1294782a-4dd7-4445-a451-590069eaa3aa")
                },
                new CartItem
                {
                    Id = Guid.Parse("e04027e6-70af-45cc-9e16-deec23671c1a")
                }
        };
    var account = new UserAccount { UserName = "m", Email = "m@m.com" };
    var mockAppManager = new Mock<ApplicationUserManager>();
    mockAppManager.Setup(c => c.FindByNameAsync("m")).ReturnsAsync(account);

    var mockRepository = new Mock<jCtrl.Services.IUnitOfWork>();
    mockRepository.Setup(x => x.CartItems.GetCustomerCart(It.IsAny<Customer>(), It.IsAny<bool>())).ReturnsAsync(cart.AsEnumerable());
    var controller = new CartsController(mockRepository.Object){
        Request = new HttpRequestMessage {RequestUri = new Uri("http://localhost/customers/9efa5332-85dc-4a49-b7af-8807742244f1/carts")},
        Configuration = new HttpConfiguration(),
        User = new ClaimsPrincipal(new GenericIdentity("fake_username"))
    };

    controller.Request.SetOwinContext(new OwinContext());
    // Act
    var custId = Guid.Parse("9efa5332-85dc-4a49-b7af-8807742244f1");
    // Act
    var actionResult = await controller.GetCartAsync(custId);
    var contentResult = actionResult as OkNegotiatedContentResult<CartReturnModel>;
    // Assert
    Assert.IsNotNull(contentResult);
    Assert.IsNotNull(contentResult.Content);
    Assert.AreEqual(1, contentResult.Content.ItemCount);
}

你知道这里出了什么问题吗?

模拟ApplicationUserManager在ASP中的单元测试.. NET Web Api

您的ApiController.User属性没有为测试设置。

我更惊讶的是User.Identity != null没有给你一个NRE。理所当然。如果通过了。那么它将根据您的测试方法返回NotFoundResult

这会导致强制转换

var contentResult = actionResult as OkNegotiatedContentResult<CartReturnModel>;

null,导致断言失败。

你需要为测试设置一个假的User

var controller = new CartsController(mockRepository.Object){
    Request = new HttpRequestMessage { RequestUri = new Uri("http://localhost/customers/9efa5332-85dc-4a49-b7af-8807742244f1/carts"),  },
    Configuration = new HttpConfiguration(),
    User = new ClaimsPrincipal(new GenericIdentity("fake_username"))
};

您还应该使测试也异步。

[TestMethod]
public async Task GetCart() {
    //Arrange
    //...other code omitted for brevity
    var username = "m";
    var customerGuid = "9efa5332-85dc-4a49-b7af-8807742244f1"; 
    var account = new UserAccount { UserName = username, Email = "m@m.com" };
    var mockAppManager = new Mock<ApplicationUserManager>();
    mockAppManager.Setup(c => c.FindByNameAsync(username)).ReturnsAsync(account);

    var mockRepository = new Mock<jCtrl.Services.IUnitOfWork>();
    mockRepository.Setup(x => x.CartItems.GetCustomerCart(It.IsAny<Customer>(), It.IsAny<bool>())).ReturnsAsync(cart.AsEnumerable());
    var requestUri = new Uri(string.Format("http://localhost/customers/{0}/carts", customerGuid));
    var controller = new CartsController(mockRepository.Object){
        Request = new HttpRequestMessage {RequestUri = requestUri},
        Configuration = new HttpConfiguration(),
        User = new ClaimsPrincipal(new GenericIdentity(username))
    };

    var custId = Guid.Parse(customerGuid);
   // Act
    var actionResult = await controller.GetCartAsync(custId);
    var contentResult = actionResult as OkNegotiatedContentResult<CartReturnModel>;
    // Assert
    Assert.IsNotNull(contentResult);
    Assert.IsNotNull(contentResult.Content);
    Assert.AreEqual(1, contentResult.Content.ItemCount);
}