views:

2104

answers:

2

Hi

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 lamdas(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.

Thanks

+5  A: 

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);
eu-ge-ne
Ya I was not sure what that 100% ment. Does it mean only First level properties?Also what you have got past that error but something else is wrong. It seems like it is not using the mock object and it tries to actually run it against the database.I have it setup the same way as I always do and I added the mock object to be used by this line:authentication.Authenticate.Provider = membershipMock.Object;
chobo2
Ok I figured it out. I totally forgot when I wrote this stuff I used stuff like Membership.GetUser();So it was never using my property that either gets a real provider or the mockup provider.So it works now.I however don't understand what the difference between these too are though:Membership.GetUser(); // what I was using before.now since I am passing it in the provider thing(since I think if I did not I would not be able to make the mock object? Like could I just use Membership instead of Membership.Provider?)I seem to get a different one.looks the same(called getUser) but only
chobo2
has like 2 overloading methods. Where as the first one has like 6.
chobo2
+1  A: 

I suppose the intermediate invocation it refers to is this: m.GetUser("test", false) since it's followed by .PasswordQuestion. What it says it that 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.

zvolkov
Ya thats what eu-ge-ne code seems to be doing but it keeps trying to but it seems like it is trying to use my database.
chobo2
@chobo2, I updated the answer. don't forget to upvote :)
zvolkov
MembershipProvider.GetUser() is abstract method; MembershipUser.PasswordQuestion is virtual property
eu-ge-ne