我使用Asp.netCore
,以下代码是我需要通过XUnit
进行测试的操作的一部分。问题是URL
在我测试操作方法时为空。如何模拟URL
及其函数RoutUrl
以返回我期望的URL
。
var callbackUrl = Url.RouteUrl("ConfirmEmail", new { userId = user.Id, token }, Request.Scheme);
我也试过这段代码,但根本不起作用。
string locationUrl = "http://location/";
var mockUrlHelper = new Mock<IUrlHelper>();
mockUrlHelper
.Setup(x => x.RoutUrl("ConfirmEmail", It.IsAny<object>(), It.IsAny<string>()))
.Returns(locationUrl);
_accountController.Url = mockUrlHelper.Object;
这是我正在测试的行动方法:
[HttpPost]
public async Task<JsonResult> SendEmailConfirmation(string email)
{
if (string.IsNullOrEmpty(email)) throw new Exception("Inavlid parameter");
var user = await _userManager.GetUserAsync(User);
if (user.Email.ToLower() == email.ToLower().Trim())
return Json(false);
user.EmailConfirmed = false;
user.Email = email;
await _userManager.UpdateAsync(user);
var token = await _userManager.GenerateChangeEmailTokenAsync(user, email);
var callbackUrl = Url.RouteUrl("ConfirmEmail", new { userId = user.Id, token }, Request.Scheme);
await _emailService.SendEmailConfirmationUserAsync(user.Email, user.FirstName, callbackUrl);
return Json(true);
}
这是我的测试:
[Fact]
public async Task SendEmailConfirmation_NewEmail_ShouldReturnTrue()
{
const string token = "TokenString";
var applicationUser = StubFactory.GetUser();
_userManagerMock
.Setup(x => x.GetUserAsync(It.IsAny<ClaimsPrincipal>()))
.ReturnsAsync(applicationUser);
_userManagerMock
.Setup(x => x.UpdateAsync(applicationUser))
.ReturnsAsync(IdentityResult.Success);
_userManagerMock
.Setup(x => x.GenerateChangeEmailTokenAsync(It.IsAny<ApplicationUser>(), It.IsAny<string>()))
.ReturnsAsync(token);
_emailServiceMock
.Setup(x => x.SendEmailConfirmationUserAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.ReturnsAsync(It.IsAny<EmailResult>());
//ToDO Mock Url.RoutUrl
string locationUrl = "http://location/";
var mockUrlHelper = new Mock<IUrlHelper>();
mockUrlHelper
.Setup(x => x.RouteUrl("ConfirmEmail", It.IsAny<object>(), It.IsAny<string>()))
.Returns(locationUrl);
_accountController.Url = mockUrlHelper.Object;
var result = await _accountController.SendEmailConfirmation("newemail@something.com");
result.Value.ShouldBe(true);
_userManagerMock.Verify(x => x.GetUserAsync(It.IsAny<ClaimsPrincipal>()), Times.Once);
_userManagerMock.Verify(x => x.GenerateChangeEmailTokenAsync(It.IsAny<ApplicationUser>(), It.IsAny<string>()), Times.Once);
_emailServiceMock.Verify(x => x.SendEmailConfirmationUserAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()), Times.Once);
}
我在单元测试会话中收到的错误消息:
System.ArgumentNullException
Value cannot be null.
Parameter name: helper
at Microsoft.AspNetCore.Mvc.UrlHelperExtensions.RouteUrl(IUrlHelper helper,
String routeName, Object values, String protocol)
答案 0 :(得分:3)
您正在嘲笑的特定RouteUrl
方法是一种扩展方法
/// <summary>
/// Generates a URL with an absolute path for the specified route <paramref name="routeName"/> and route
/// <paramref name="values"/>, which contains the specified <paramref name="protocol"/> to use.
/// </summary>
/// <param name="helper">The <see cref="IUrlHelper"/>.</param>
/// <param name="routeName">The name of the route that is used to generate URL.</param>
/// <param name="values">An object that contains route values.</param>
/// <param name="protocol">The protocol for the URL, such as "http" or "https".</param>
/// <returns>The generated URL.</returns>
public static string RouteUrl(
this IUrlHelper helper,
string routeName,
object values,
string protocol)
{
if (helper == null)
{
throw new ArgumentNullException(nameof(helper));
}
return helper.RouteUrl(routeName, values, protocol, host: null, fragment: null);
}
最终包含到创建UrlRouteContext
的{{3}}。
由于Moq无法模拟扩展方法,因此您需要模拟该类以使扩展方法流程完成
string locationUrl = "http://location/";
var mockUrlHelper = new Mock<IUrlHelper>();
mockUrlHelper
.Setup(x => x.RouteUrl(It.IsAny<UrlRouteContext>()))
.Returns(locationUrl);