2017-08-24 2 views
1

J'utilise Asp.netCore et le code suivant fait partie de mon action que j'ai besoin de tester par XUnit. Le problème est URL qui est nul pendant que je teste la méthode d'action. Comment puis-je simuler URL et sa fonction RoutUrl pour retourner un URL que je m'attends. J'ai également essayé ce code, mais cela ne fonctionne pas du tout.Mocking Url.RouteUrl

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; 

Ceci est ma méthode d'action en cours de test:

[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); 
} 

Et voici mon test:

[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("[email protected]"); 

    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); 
} 

message d'erreur que je reçois en séance de test unitaire:

System.ArgumentNullException 
Value cannot be null. 
Parameter name: helper 
at Microsoft.AspNetCore.Mvc.UrlHelperExtensions.RouteUrl(IUrlHelper helper, 
String routeName, Object values, String protocol) 

Répondre

2

Le particulier RouteUrl méthode vous moquez est une méthode d'extension

/// <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); 
} 

Source: UrlHelperExtensions.cs

qui enveloppe finalement vers le bas pour another extension method qui crée UrlRouteContext.

Depuis Moq ne parvient pas à se moquer des méthodes d'extension, cette classe est ce que vous auriez besoin de se moquer de faire le flux de méthode d'extension jusqu'à la fin

string locationUrl = "http://location/"; 
var mockUrlHelper = new Mock<IUrlHelper>(); 
mockUrlHelper 
    .Setup(x => x.RouteUrl(It.IsAny<UrlRouteContext>())) 
    .Returns(locationUrl);