Moq and Code Contracts

放肆的年华 提交于 2019-12-10 15:26:26

问题


When using class invariants, Code contracts seems to inject code everywhere. Stuff like this

[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);

Fails with an error message

Could not locate event for attach or detach method Void $InvariantMethod$().

Anyone know of a solution?


回答1:


This unit test "passes" when run without generating exceptions:

[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);
    }
}

I'm not entirely sure what's going on and how you're compiling (or transcribing) the above, but I don't think you can have "ContractClassFor" attribute decorating an interface, and you certainly can't have the implementation "{ ... }" in an interface. You also need to make your interface IX public to mock it (or else internal with InternalsVisibleTo() castle proxy in your properties).

Hopefully this helps, but feel free to update your post with new code if this doesn't lead you toward what you're looking to do.




回答2:


Your code is incorrect. It should look like this:

[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); 

Notice that the Contract class is Internal Abstract, and that it also now implements your interface. The Invariant isn't appropiate there, as that's for implemenation details; you don't know how people will implemenent your interface, so don't put it there. Also the attribute for invariant methods is ContractInvariantMethodAttribute.



来源:https://stackoverflow.com/questions/6390348/moq-and-code-contracts

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!