使用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)或者我应该寻找另一个模拟框架来实现这一目标?
答案 0 :(得分:2)
不,Moq(就像任何继承类一样)不能覆盖非虚方法,所以除非你可以使Name成为虚拟属性(通过更改或包装类),否则它不能被Moq模拟。
我建议您尽可能将您的属性更改为虚拟属性,因为这样可以使用任何模拟框架。据我所知,只有3个可以模拟非虚拟方法,没有一个是免费的;
Fakes
(我相信终极版)答案 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
,这样做非常简单。