2015-03-08 54 views
1

我是新來的合同,我從概述中瞭解到它可以幫助您在編譯時發現合同違規。如何獲得編譯時合同警告/錯誤

當我有明確違反合同的代碼時,我沒有收到編譯時警告或錯誤。

我希望在測試中設置Person.Name = null的代碼行會給我一個警告或錯誤,因爲它違反了合同。

如何調整我的代碼以獲取編譯時間消息?

說明:爲了澄清,我把它放在單元測試中的唯一原因是得到編譯時間消息。測試本身目前通過,這是一個運行時間方面;我想它應該通過,因爲它是編譯時測試而不是運行時測試。無論如何,問題是關於編譯時間消息還是缺乏,而不是關於單元測試結果。被測

代碼:

using System; 
using System.Diagnostics.Contracts; 

namespace DomainModel 
{ 
    [ContractClass(typeof(IPersonContract))] 
    public interface IPerson 
    { 
     string Name { get; set; } 
    } 

    [ContractClassFor(typeof(IPerson))] 
    public abstract class IPersonContract : IPerson 
    { 
     private IPersonContract() { } 

     string IPerson.Name 
     { 
      get 
      { 
       throw new NotImplementedException(); 
      } 
      set 
      { 
       Contract.Ensures(!string.IsNullOrEmpty(value)); 
      } 
     } 
    } 

} 

這裏是我的測試:

using Moq; 
using NUnit.Framework; 
using DomainModel; 

namespace Unit 
{ 
    /// <summary> 
    /// A test class for IPerson 
    /// </summary> 
    [TestFixture()] 
    public class IPersonShould 
    { 

     #region "Unit Tests" 

     [Test()] 
     public void ThrowWhenIPersonIsGivenEmptyName() 
     { 
      //set up 
      IPerson IPerson = this.Person; 
      string expectedResult = null; 
      //Dim NameParam1 as String = Nothing 
      Person.Name = null; // Would expect this line to generate warning or error 
      //perform test 
      string actualResult = IPerson.Name; 

      //compare results 
      Assert.AreEqual(expectedResult, actualResult); 

     } 
     #endregion 

     #region "Setup and Tear down" 

     private class MyPerson : IPerson { 

      private string name; 
      public string Name 
      { 
       get 
       { 
        return name; 
       } 
       set 
       { 
        name = value; 
       } 
      } 
     } 

     private MyPerson Person; 

     /// <summary> 
     /// This runs only once at the beginning of all tests and is used for all tests in the 
     /// class. 
     /// </summary> 
     [TestFixtureSetUp()] 
     public void InitialSetup() 
     { 
      Person = new MyPerson(); 
     } 

     /// <summary> 
     /// This runs only once at the end of all tests and is used for all tests in the class. 
     /// </summary> 
     [TestFixtureTearDown()] 
     public void FinalTearDown() 
     { 
     } 

     /// <summary> 
     /// This setup function runs before each test method 
     /// </summary> 
     [SetUp()] 
     public void SetupForEachTest() 
     { 

     } 

     /// <summary> 
     /// This setup function runs after each test method 
     /// </summary> 
     [TearDown()] 
     public void TearDownForEachTest() 
     { 

     } 

     #endregion 

    } 

} 

這裏是我的當前設置: enter image description here

回答

0

我想你可能會有點困惑代碼合同如何幫助您和其他開發人員,所以讓我嘗試提供幫助。

有一對夫婦的方式,其代碼契約試圖幫助:

  1. 與合同註解類提供誰引用您的庫第三方開發商誰也使用代碼契約知道是否不是他們正確使用你的庫。
    • 這是由於在運行時拋出的異常而產生的,至少是Debug構建。異常的類型取決於您正在使用庫的合同類型。
  2. 對於您的團隊中的開發人員,上述數字1也是如此。此外,代碼合同可以爲您的代碼提供合同,爲您的團隊提供靜態分析
    • 靜態分析是編譯啓用靜態分析的項目後出現的警告和信息/事件項目。

如你所知,您可以啓用代碼契約進行靜態分析(即「編譯時」)和運行時間的合同每個項目的基礎上檢查。

看來已啓用兩個執行運行時檢查合同和執行靜態合同上的的DomainModel項目檢查執行靜態合同檢查將允許編譯器在執行構建後通知您和您的團隊潛在合同問題。

但真正的問題是,您在單元測試項目中定義了Person。您是否啓用在單元測試項目中執行靜態合同檢查?如果沒有,因爲Person在那裏定義,除非啓用它,否則在單元測試項目上不會發生靜態分析。

而且,因爲你是在單元測試項目定義Person,你還需要啓用執行運行時檢查合同爲調試版本的單元測試項目,太。這是不可取的,因爲它會導致單元測試花費更長的時間來編譯。我知道你打算最終移動實現,因爲你只是想了解你迄今爲止編寫的代碼。另一方面,如果您需要使用任何類型的測試雙打(例如間諜),您可以通過定義一個包含測試的獨立程序集來緩解在單元測試項目中啓用此選項的需要 - 使您的單元測試需要雙倍,並在此測試雙打組件上啓用代碼合同。

+0

我不再有這個項目。我無法去嘗試一下,看看這個答案是否解決了這個問題。你可以用我的代碼設置一個項目,並在你的答案被應用後給出編譯器警告的屏幕截圖嗎?我很抱歉要你這樣做。 – toddmo 2016-03-03 19:22:01