在这种情况下我可以使用Moq吗?

时间:2012-09-17 04:23:50

标签: .net unit-testing mocking moq-3

使用Moq模拟此对象有什么可能的解决方法。返回的错误消息是: “非虚拟(在VB中可覆盖)成员的设置无效: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");

注意:我正在尝试模拟X509SecurityToken。 这是被测试的课程:

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.");
}

}

为此做任何工作(使用Moq)或者我应该寻找另一个模拟框架来实现这一目标?

2 个答案:

答案 0 :(得分:2)

不,Moq(就像任何继承类一样)不能覆盖非虚方法,所以除非你可以使Name成为虚拟属性(通过更改或包装类),否则它不能被Moq模拟。

我建议您尽可能将您的属性更改为虚拟属性,因为这样可以使用任何模拟框架。据我所知,只有3个可以模拟非虚拟方法,没有一个是免费的;

答案 1 :(得分:0)

您可以寻找一些框架,允许您“破解”无法简单模拟的代码(即不包含虚拟方法/不是接口),但这可能是过度的(并且某些选项不是免费的例如TypeMock Isolator

更简单的方法可能是抽象X509SecurityToken,例如:

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

然后,实现一个包装器,它也实现了上面指定的接口:

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

然后,在整个代码中,您应该使用ISecurityToken接口而不是X509SecurityToken,这样做非常简单。