2012-02-03 7 views
49

Con Moq, ¿es válido tener más de un argumento coincidente?Multiple Moq It.Is <string>() Argumentos coincidentes

It.Is<string>() 

En este ejemplo quiero que el mockMembershipService para devolver una ProviderUserKey diferente dependiendo del usuario que se suministra.

mockMembershipService.Setup(
    x => x.GetUser(
     It.Is<string>(
     s => s.Contains("Joe"))) 
    .ProviderUserKey) 
.Returns("1234abcd"); 


mockMembershipService.Setup(
    x => x.GetUser(
    It.Is<string>(
     s => s.Contains("Tracy"))) 
    .ProviderUserKey) 
.Returns("5678efgh"); 

La configuración por defecto es la segunda sentencia en lugar de evaluar cada uno por sus propios méritos.

Respuesta

31

¿No es confuso? Está intentando simular el método GetUser, pero establece los retornos para la propiedad del valor devuelto de esa función. También desea indicar la propiedad del tipo de devolución según el método de burla.

Aquí está una manera de una manera más clara:

mockMembershipService.Setup(x => x.GetUser(It.IsAny<string>()) 
        .Returns<string>(GetMembershipUser); 

Aquí es un método para crear la maqueta de la membresía:

private MembershipUser GetMembershipUser(string s) 
{ 
    Mock<MembershipUser> user =new Mock<MembershipUser>(); 
    user.Setup(item => item.ProviderUserKey).Returns(GetProperty(s)); 
    return user.Object; 
} 

A continuación, se escribe un método de fijación de este inmueble:

private string GetProperty(string s) 
{ 
    if(s.Contains("Joe")) 
     return "1234abcd"; 
    else if(s.Contains("Tracy")) 
     return "5678efgh"; 
} 
+1

Lo intentaré en breve, estaba viendo este video http://thethoughtfulcoder.com/blog/52/Moq-Use-Setup-arguments-parameters-in-the-Returns-of-amounted-function mientras agregaba su respuesta que hace algo similar –

+0

el código anterior no compila se queja de Security.MembershipUser no contiene una referencia para devoluciones y también sobre User que no contiene ninguna definición para ProviderUserKey –

+0

Debe hacer referencia al ensamblado que contiene Security.MembershipUser, supongo. O puede inyectar una dependencia para crear usuarios para usted en su MembershipService –

11

Las llamadas de configuración satisfactoria anulan las configuraciones anteriores.

Usted podría utilizar su argumento en su devolución de llamada de retorno:

mockMembershipService.Setup(x => x.GetUser(It.IsAny<string>()).ProviderUserKey).Returns<string>(s => 
{ 
    if(s.Contains("Joe")) 
     return "1234abcd"; 
    else if(s.Contains("Tracy")) 
     return "5678efgh"; 
}); 

Si es importante para usted para hacer valer el argumento pasado, también es necesario It.Is<string>(...) en lugar de It.IsAny<string>(...).

+0

que debería llegar a probar esto en aproximadamente 2 horas. –

+0

El código arroja una discrepancia en el conteo de parámetros –

+0

Ah, bueno, creo que es porque estamos configurando una propiedad aquí ('ProviderUserKey'), mientras que el argumento sobre el que intentamos actuar proviene de' GetUser (...) ' . No puedo verificar la solución correcta en este momento, pero si sigues los consejos de Ufuk, debería estar bien ... – Bartosz

24

Si desea restringir la entrada a solo "Joe" y "Tracy", puede especificar varias condiciones en It.Is<T>(). Algo así como

mockMembershipService.Setup(x => x.GetUser(It.Is<String>(s => s.Contains("Joe") 
                 || s.Contains("Tracy"))) 
    .Returns<string>(/* Either Bartosz's or Ufuk's answer */); 
+0

no es que quiero restringir per se, solo quiero evaluar lo que la entrada y devolver el resultado deseado :-) –

+0

Independientemente de si esto estaba en el lugar correcto, me ayudó, gracias @ cadrell0 –

3

Por favor, compruebe la documentación Introduction to Moq > Matching Arguments:

// matching Func<int>, lazy evaluated 
mock.Setup(foo => foo.Add(It.Is<int>(i => i % 2 == 0))).Returns(true); 


// matching ranges 
mock.Setup(foo => foo.Add(It.IsInRange<int>(0, 10, Range.Inclusive))).Returns(true); 


// matching regex 
mock.Setup(x => x.DoSomething(It.IsRegex("[a-d]+", RegexOptions.IgnoreCase))).Returns("foo"); 
+2

Ahora con más experiencia en pruebas unitarias, no recomiendo este tipo de enfoque. Deberíamos evitar poner la lógica dentro de las Pruebas Unitarias. Otra opción es crear pruebas unitarias separadas: una para ** Joe ** y otra para ** Tracy ** – Jaider

Cuestiones relacionadas