Pete Maroun
Pete Maroun

Reputation: 2075

Can I use Moq in this situation?

What possible work-around do I have for mocking this object using Moq. The error message returned is: "Invalid setup on a non-virtual (overridable in VB) member: p => p.Certificate.SubjectName.Name"

        var st = new Mock<X509SecurityToken>();
        st.SetupGet(p => p.Certificate.SubjectName.Name).Returns("test1");
        var target = new X509IssuerNameRegistry("test1", "test2");

        var actual = target.GetIssuerName(st.Object);

        Assert.AreEqual<string>("test1", actual, "Actual security token did not equal expected security token");

Note: I am trying to Mock X509SecurityToken. Here is the class under test:

public class X509IssuerNameRegistry : IssuerNameRegistry { readonly List _trustedSubjectNames = new List();

public X509IssuerNameRegistry(params string[] trustedSubjectNames)
{
    _trustedSubjectNames = new List<string>(trustedSubjectNames);
}

public override string GetIssuerName(SecurityToken securityToken)
{
    var x509Token = securityToken as X509SecurityToken;
    if (x509Token != null)
    {
        if (_trustedSubjectNames.Contains(x509Token.Certificate.SubjectName.Name))
        {
            return x509Token.Certificate.SubjectName.Name;
        }
    }
    throw new SecurityTokenException("Untrusted issuer.");
}

}

Any work-rounds for this (using Moq) or should I look to another mocking framework to accomplish this?

Upvotes: 3

Views: 1237

Answers (2)

Joachim Isaksson
Joachim Isaksson

Reputation: 180887

No, Moq (just like any inheriting class) cannot override non-virtual methods, so unless you can make Name a virtual property (by changing or wrapping the class), it cannot be mocked by Moq.

I'd suggest that you if possible change your property to be virtual, since that will allow you to use any mocking framework. As far as I know there are only 3 that can mock non virtual methods, none of them free;

Upvotes: 2

Bartosz
Bartosz

Reputation: 3358

You could look for some framework that allows you to 'hack' the code that cannot be mocked simply (i.e. does not contain virtual methods/is not an interface), but that could be overkill (and some options are not free like TypeMock Isolator for example).

An easier approach might be to abstract X509SecurityToken, for example:

interface ISecurityToken
{
    string SubjectName { get; }
    // ...
}

Then, implement a wrapper which also implements interface specified above:

class SecurityToken : ISecurityToken
{
    X509SecurityToken token;
    public SecurityToken(X509SecurityToken token)
    {
        this.token = token;
    }
    public string SubjectName { get { return token.SubjectName.Name; } }
}

Then, throughout your code, you should use ISecurityToken interface instead of X509SecurityToken, which would be rather straightforward to mock.

Upvotes: 0

Related Questions