2011-06-17 10 views
5

クラスインバリアントを使用するとき、コードコントラクトはどこにでもコードを挿入するようです。このMoqとコードコントラクト

[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$(). 

誰もが解決策を知っているエラーメッセージで失敗しますか?

+0

私たちは正確に何を見ていますか? –

+0

さらにいくつかのコードを追加しました – jameszhao00

+0

その 'ClassInvariant'属性はどこから来ましたか? – Jonn

答えて

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"属性でインターフェースを装飾することができると思うし、あなたは確かにインターフェースで "{...}"の実装を持つことはできません。あなたはまた、あなたのプロパティのInternalsVisibleTo()城のプロキシでそれを模擬するためにあなたのインターフェイスIXをパブリックにする必要があります。

これが役立ちますが、あなたが探しているものにつながっていない場合は、新しいコードで投稿を更新することをお勧めします。

+0

変更にはいくつか問題があります。 IXContractは内部だけでなく、抽象的でなければなりません。不変量法はそこでは適切ではない。あなたがインプリメンテーションのプロパティとフィールドをチェックしているときには、実際には可能ではありません。皆がどのようにインターフェイスを実装するかは分かりません。また、このContractクラスは実際の実装ではなく、インタフェース上の契約を可能にするための接着剤として存在します。また、クラスはIXインタフェースを実装しなければならない(MUST)。どのように見えるべきか私の答えを見てください。 – 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です。