【问题标题】:Can I use Moq in this situation?在这种情况下我可以使用起订量吗?
【发布时间】:2012-09-09 07:20:54
【问题描述】:

我有什么可能的解决方法来使用 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。 这是被测试的类:

公共类 X509IssuerNameRegistry:IssuerNameRegistry { 只读 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)还是我应该寻找另一个模拟框架来完成这个?

【问题讨论】:

  • 如果 st 对象在您的代码 sn-p 中没有任何用途,但动态代理库在这种情况下可能会有所帮助
  • 谢谢 Jani.. 更正了代码 sn-p。

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


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    您可以寻找一些框架,允许您“破解”无法简单模拟的代码(即不包含虚拟方法/不是接口),但这可能是矫枉过正(有些选项不是免费的,比如以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,这将是相当简单的模拟。

    【讨论】:

    • 解决这个问题是我写这篇文章的初衷。我用正在测试的代码更新了原始帖子。当我从 BCL 覆盖基类方法时如何设计?
    猜你喜欢
    • 2012-03-28
    • 2016-09-12
    • 2016-11-07
    • 2022-08-05
    • 2018-05-05
    • 1970-01-01
    • 2022-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多