问题
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