2009-06-27 5 views
11

Quiero probar mi parte del código que devuelve la pregunta de la contraseña de los usuarios. Así que hice una maqueta del proveedor de Membresía usando Moq.Cómo configuro esto (Configuración de Moq)

No creo que deba mostrarle el código real solo la parte de prueba.

// Arrange 
var membershipMock = new Mock<MembershipProvider>(); 
membershipMock.Setup(m => m.GetUser("test", false).PasswordQuestion).Returns("Password"); 
authentication.Authenticate.Provider = membershipMock.Object; 

// Act 
var actual = authentication.PasswordRecoveryStep1(It.IsAny<string>()); 

// Assert 
Assert.That(actual, Is.EqualTo("Password")); 

Así que cuando corro en este Nunit me sale esto:

Test.Controllers.AuthenticationControllerTest.Test_If_Password_Recovery_Setp1_Returns_Users_PasswordQuestion: 
System.NotSupportedException : Only property accesses are supported in intermediate invocations on a setup. Unsupported expression m.GetUser("test", False). 

at Moq.Mock.AutoMockPropertiesVisitor.VisitMethodCall(MethodCallExpression m) 
at Moq.ExpressionVisitor.Visit(Expression exp) 
at Moq.Mock.AutoMockPropertiesVisitor.VisitMemberAccess(MemberExpression m) 
at Moq.ExpressionVisitor.Visit(Expression exp) 
at Moq.Mock.AutoMockPropertiesVisitor.SetupMocks(Expression expression) 
at Moq.Mock.GetInterceptor(LambdaExpression lambda, Mock mock) 
at Moq.Mock.<>c__DisplayClass15`2.<SetupGet>b__14() 
at Moq.PexProtector.Invoke[T](Func`1 function) 
at Moq.Mock.SetupGet[T1,TProperty](Mock mock, Expression`1 expression) 
at Moq.Mock.<>c__DisplayClass12`2.<Setup>b__11() 
at Moq.PexProtector.Invoke[T](Func`1 function) 
at Moq.Mock.Setup[T1,TResult](Mock mock, Expression`1 expression) 
at Moq.Mock`1.Setup[TResult](Expression`1 expression) 
at Test.Controllers.AuthenticationControllerTest.Test_If_Password_Recovery_Setp1_Returns_Users_PasswordQuestion() in D:\MvcApplication9\Test\Controllers\AuthenticationControllerTest.cs:line 186 

Así que supongo que es algo debido a la propiedad que estoy tratando de acceder. No estoy seguro de cómo configurarlo. No soy muy bueno con lambdas (y aún no he podido encontrar un tutorial sobre ellos), así que no estoy seguro de si podría arreglarlo de otra manera para que funcione.

O si me perdí totalmente la marca.

Respuesta

13

La respuesta está en mensaje de excepción:

... Sólo accesos de propiedad están soportados en las invocaciones intermedios en una configuración ...

Prueba esto:

var user = new Mock<MemberShipUser>(); 
user.SetupGet(x => x.PasswordQuestion).Returns("Password"); 

membershipMock.Setup(m => m.GetUser("test", false)).Returns(user.Object); 
+1

Ya no estaba seguro de qué es eso 100% ment. ¿Significa solo propiedades de primer nivel? También lo que ha pasado ese error, pero algo más está mal. Parece que no está utilizando el objeto simulado e intenta ejecutarlo contra la base de datos. Lo tengo configurado de la misma manera que siempre lo hago y he agregado el objeto simulado que utilizará esta línea: authentication.Authenticate.Provider = membershipMock.Object; – chobo2

+0

Ok lo descubrí. Olvidé por completo que cuando escribí esto usé cosas como Membership.GetUser(); Así que nunca usé mi propiedad para obtener un proveedor real o el proveedor de maquetas. Así que funciona ahora. Sin embargo, no entiendo cuál es la diferencia entre estos también: Membresía.GetUser(); // lo que estaba usando antes. ahora desde que estoy pasando en el que el proveedor (ya que creo que si no lo hiciera, no sería capaz de hacer que el objeto de burla? Como podría yo sólo uso de la membresía en lugar de Membership.Provider?) me parecen llegar uno diferente tiene el mismo aspecto (llamado getUser) pero solo – chobo2

+0

tiene como 2 métodos de sobrecarga. Donde el primero tiene como 6. – chobo2

2

Supongo que la invocación intermedia a la que se refiere es la siguiente: m.GetUser("test", false) ya que es seguido por .PasswordQuestion. Lo que dice es: no se puede tener un método utilizado como un trozo intermedio, solo una propiedad. Este marco particular parece admitir stubs intermedios (es decir, construye X.Y en la definición de stub, observe el punto) pero la mayoría de los otros no.

Los códigos no son mágicos, lo único que pueden hacer es interceptar sus llamadas y sustituir el resultado devuelto con el valor proporcionado. En su caso, su trozo de GetUser necesita devolver un simulacro de usuario, con su PasswordQuestion apagada para devolver "Contraseña".

Otro problema con su código es que se está burlando de MembershipProvider directamente. La forma en que funciona la mayoría del marco de burla, si se burla de una interfaz, generan dinámicamente una clase que la implementa, y cuando se burla de una clase, generan una clase que hereda de ella y anula cualquier método virtual. Sin embargo, si el método no es virtual, no puede anularlo, de ahí el comportamiento mixto que puede observar. Sugiero que veas si hay una interfaz como IMembershipProvider y, en caso afirmativo, utiliza eso en tu código en lugar de una clase concreta.

+0

Ya es lo que el código de eu-ge-ne parece estar haciendo, pero sigue intentándolo, pero parece que está tratando de usar mi base de datos. – chobo2

+0

@ chobo2, actualicé la respuesta. no se olvide de votar :) – zvolkov

+0

MembershipProvider.GetUser() es un método abstracto; MembershipUser.PasswordQuestion es propiedad virtual –

Cuestiones relacionadas