Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I setup this (Moq Setup)

I want to test my part of code that returns the users password question. So I have made a mockup of the Membership provider using Moq.

I don't think I need to show you the actual code just the test part of it.

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

So when I run this in Nunit I get this:

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

So I am guessing it is something because of the property that I am trying to access. I am not sure how to set it up. I am not very good with lambdas (and have not been able to find a tutorial on them yet) so I am not sure if I could some how arrange it differently to make it work.

Or if I just totally missed the mark.

like image 412
chobo2 Avatar asked Jun 27 '09 11:06

chobo2


2 Answers

The answer is in exception message:

... Only property accesses are supported in intermediate invocations on a setup ...

Try this:

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

membershipMock.Setup(m => m.GetUser("test", false)).Returns(user.Object);
like image 166
eu-ge-ne Avatar answered Oct 06 '22 02:10

eu-ge-ne


I suppose the intermediate invocation it refers to is this: m.GetUser("test", false) since it's followed by .PasswordQuestion. What it says is: you can't have a method used as an intermediate stub, only a property. This particular framework does seem to support intermediate stubs (i.e. constructs X.Y in the stub definition, note the dot) but most others don't.

Stubs are not magic, all they can do is intercept your calls and substitute the returned result with your provided value. In your case, your stub of GetUser needs to return a mock of user, with its PasswordQuestion stubbed away to return "Password".

Another problem with your code is that you're mocking MembershipProvider directly. The way most of mocking framework work, if you mock an interface, they dynamically generate a class that implements it, and when you mock a class, they generate a class that inherits from it and overrides any virtual methods. However, if method is not virtual it can't override it, hence the mixed behavior you may observe. I suggest you see if there's an interface like IMembershipProvider and if yes, use that in your code instead of concrete class.

like image 34
Stop Putin Stop War Avatar answered Oct 06 '22 00:10

Stop Putin Stop War