Moq和Code Contracts

5
当使用类不变量时,代码合约似乎会在各个地方注入代码。像这样的东西:
[ContractClassFor(typeof(IX))]
interface IXContract  
{  
    [ClassInvariant]
    void Invariant() { ... }
}

[ContractClass(typeof(IXContract))]
interface IX { event EventHandler b; }

var a = new Mock<IX>();

a.Raise(x => x.b += null);

失败并显示错误信息。
Could not locate event for attach or detach method Void $InvariantMethod$().

有人知道解决方案吗?


我们确切地在看什么? - H H
那个 ClassInvariant 属性是从哪里来的? - Jonn
@jameszhao00 好久不见了,之前的回答有帮到你吗? - Andy
2个回答

3

当运行时不产生异常,这个单元测试就会“通过”:

[ContractClassFor(typeof(IX))]
class IXContract
{
    [ContractInvariantMethod]
    void Invariant() { }
}

[ContractClass(typeof(IXContract))]
public interface IX { event EventHandler b; }

/// <summary>
/// Summary description for UnitTest1
/// </summary>
[TestClass]
public class UnitTest1
{
    public void MyTest()
    {
        var a = new Mock<IX>();

        a.Raise(x => x.b += null);
    }
}

我不是完全确定您在编译(或转录)上述内容时发生了什么,但我认为您不能使用“ContractClassFor”属性修饰接口,并且您肯定不能在接口中使用实现“{ ... }”。您还需要将接口IX公开以模拟它(否则,在属性中使用Internal与InternalsVisibleTo() Castle代理)。希望这可以帮助您,但如果这不能带您朝着您想要做的方向前进,请随时更新您的帖子并发布新代码。

你的更改有几个问题。IXContract 应该是抽象的,而不仅仅是内部的。Invariant 方法在那里不合适。拥有一个并不是真正可能的,因为你正在检查实现的属性和字段,而你不知道每个人将如何实现接口。此外,这个 Contract 类并不是实际的实现,它只是作为粘合剂允许在接口上使用契约。此外,这个类必须实现 IX 接口。请参见我的答案,了解它应该是什么样子。 - Andy

2

您的代码有误。正确的代码如下:

[ContractClassFor(typeof(IX))] 
internal abstract class XContract : IX
{   
    // Invariants belong on your actual implemenation; interfaces don't dictate implemenation so this isn't appropariate here.
    // [ ContractInvariantMethod] 
    // void Invariant() { ... } 

    public event EventHandler b { get { return default(EventHandler); } set { }}
} 

[ContractClass(typeof(XContract))] 
interface IX { event EventHandler b; } 

var a = new Mock<IX>(); 

a.Raise(x => x.b += null); 

请注意,Contract类是内部抽象的,并且现在实现了您的接口。 那里不适合不变量,因为那是用于实现细节的; 您不知道人们将如何实现您的接口,因此不要将其放在那里。 另外,不变方法的属性是ContractInvariantMethodAttribute


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接