views:

484

answers:

2

Hi,

I created a custom RoleProvider (standard webforms, no mvc) and I would like to test it. The provider itself integrates with a custom implementation of IIdentity (with some added properties).

I have this at the moment:

var user = new Mock<IPrincipal>();
var identity = new Mock<CustomIdentity>();

user.Setup(ctx => ctx.Identity).Returns(identity.Object);
identity.SetupGet(id => id.IsAuthenticated).Returns(true);
identity.SetupGet(id => id.LoginName).Returns("test");

// IsAuthenticated is the implementation of the IIdentity interface and LoginName

However when I run this test in VS2008 then I get the following error message:

Invalid setup on a non-overridable member: id => id.IsAuthenticated

Why is this happening? And most important, what do I need to do to solve it?

Grz, Kris.

A: 

Are you mocking against the interface IIdentity, or mocking against your custom type?

Without having a fuller code snippet to look at, I am guessing that it is complaining that the IsAuthenticated is not marked as virtual in your custom implementation. However, this could only be the case if you were mocking against the concrete type, not the interface.

Rob Levine
I'm indeed mocking against the concrete class as this is a custom implementation of IIdentity from another team delivered as an assembly. The IsAuthenticated property is not virtual (nor is the LoginName property).
XIII
ok - then you will need to mark IsAuthenticated as virtual in your concrete class. This should fix the problem.
Rob Levine
Reading your replies below, it seems like you don't have the option to mark this as virtual. In this case, you *may* want to consider putting your own *wrapper* class around the "unmockable" class and using this in your code. You can then ensure the wrapper is mockable. See a post by me from a few days ago on this: http://stackoverflow.com/questions/1182338/1182430#1182430
Rob Levine
+3  A: 

You should mock IIdentity (instead of CustomIdentity - only possible if the variables you are mocking are declared in the interface) or declare the used variables as virtual.


To mark as virtual, do this: In your concrete class CustomIdentity, use

public virtual bool isAuthenticated { get; set; }

instead of

public bool isAuthenticated { get; set; }


Moq and other free mocking frameworks doesn't let you mock members and methods of concrete class types, unless they are marked virtual.

Finally, you could create the mock yourself manually. You could inherit CustomIdentity to a test class, which would return the values as you wanted. Something like:

internal class CustomIdentityTestClass : CustomIdentity
{
    public new bool isAuthenticated
    {
        get
        {
            return true;
        }
    }

    public new string LoginName
    {
        get
        {
            return "test";
        }
    }

}

This class would be only used in testing, as a mock for your CustomIdentity.

--EDIT

Answer to question in comments.

Samuel Carrijo
What do you mean by declare the used variables as virtuals? You mean in my test itself?
XIII
@XIII added explanation. It should be done in your concrete class
Samuel Carrijo
Thx for explanation. However I don't have access to the code of the custom IIdentity implementation. Is there a workaround?
XIII
@XIII Sorry, free mocking frameworks for c# can't do it. If possible, mock IIdentity instead of CustomIdentity, then you'll be able to do it. Alternatively, you could make the mock manually
Samuel Carrijo
I tried but the properties I need to test are not default implementations of IIdentity so it won't compile when I simply mock IIdentity directly.
XIII
what about the manual mock?
Samuel Carrijo
@XIII oh yeah, the new keyword to override the base implementation :). Gonna update my answer
Samuel Carrijo
And please upvote/accept answer if it works for u ;)
Samuel Carrijo
Indeed :-). That seems to work. Now just try to get the mocked context into the Provider itself (but that's another question).
XIII
Yay, thanks. About the provider, I'd recommend asking another question. Still getting familiar with webforms...
Samuel Carrijo