2011-06-17 69 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」屬性,並且你肯定不能在接口中實現「{...}」。你還需要公開你的接口IX來模擬它(或者在你的屬性中使用InternalsVisibleTo()castle代理內部)。

希望這會有所幫助,但如果這不會引導您找到您想要做的事情,請隨時用新代碼更新您的文章。

+0

您的更改也有一些問題。 IXContract應該是抽象的,而不僅僅是內部的。不變法不適合那裏。當你檢查實現的屬性和字段時,有一個並不是真的可能,你不知道每個人將如何實現接口。此外,這個合同類不是實際的實現,它在那裏作爲粘合劑來允許接口上的合同。此外,該類必須實現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); 

請注意合同類是內部摘要,並且它現在也實現了您的接口。不變式不適合那裏,因爲這是實現細節;你不知道人們將如何實現你的界面,所以不要把它放在那裏。不變方法的屬性也是ContractInvariantMethodAttribute