2014-04-18 48 views
0

我有一些測試代碼似乎用完了正確的順序。測試訂單Microsoft.VisualStudio.TestTools.UnitTesting問題?

[TestClass] 
public class DirTest { 
    public DirTest() { 
    Assert.AreEqual(Directory.Exists("testpath"), true); 
    } 

    [TestMethod] 
    public void TestMethod1() { 
    } 

    [ClassInitialize] 
    public static void InitTest(TestContext context) { 
    Directory.CreateDirectory("testpath"); 
    } 
} 

它拋出該目錄不存在,類構造函數被調用或者是有什麼我需要做的是缺少前不應ClassInitialize運行錯誤。如果情況並非如此,除了AssemblyInitialize之外,還有一個測試用例可以包含在構造類之前調用​​的測試中嗎?

- 編輯 真正的問題在這裏,頂部是一個簡化。

//RealClass.cs 
public class RealClass{ 
    public RealClass(string path){ 
    this._path = path; 
    this._InitDirectory(); 
    } 

    protected string _path; 
    protected void _InitDirectory(){ 
    //Something that requires read from path 
    File.WriteAllText(this._path + "/realData.data", "some real data that needs to be created by the class"); 
    } 
} 

//DirTest.cs 
[TestClass] 
public class DirTest : RealClass { 
    public DirTest() : base("testpath") {} 

    [TestMethod] 
    public void TestMethod1() { 
    } 

    [ClassInitialize] 
    public static void InitTest(TestContext context) { 
    Directory.CreateDirectory("testpath"); 
    } 
} 

單元測試將失敗,因爲其中需要的路徑「ClassInitialize」方法之前將死的目錄被調用來創建所需的模擬目錄。

- 編輯

我想出了一個變通對於這一點,但我仍想知道是否有另一種方式來達到預期的效果而無需添加更多的類,並且不移除的功能考試。我爲剛剛包含該靜態方法的類設置了一個「AssemblyInitialize」,並告訴該方法爲「ClassInitialize」激發靜態方法。它當然會在任何構造函數之前觸發。雖然問題的根源仍然沒有解決,因爲它不是自包含的,而是依賴於類函數來調用類設置。

+0

你真的有相對路徑還是隻顯示它的樣本? (事實上​​,創建文件夾對於單元測試來說不是個好主意,但它不是這個問題的一部分)。 –

+0

構造函數總是首先執行。 –

+0

這個想法是以一種簡單的方式顯示,如果我要在構造類之前測試具有需要某些東西的繼承的類,它將無法創建該類。如果你的課堂需要文件夾進行測試,那麼不是測試創建和銷燬它們以進行測試並不是一個壞主意,你還有什麼能夠分享你的測試?我明白,當一個類正在創建構造函數總是被稱爲第一,但這是一個靜態方法。如果這個想法要求建造這個班,爲什麼會是靜態的? – Stev0

回答

0

更新您的代碼如下:

[TestClass] 
public class DirTest { 
    public DirTest() { } 

    [TestMethod] 
    public void TestMethod1() { 
    } 

    [ClassInitialize] 
    public static void InitTest(TestContext context) { 
      if (!Directory.Exists("testpath")) { 
       Directory.CreateDirectory("testpath"); 
      } 
    } 
} 
+0

Assert.AreEqual(Directory.Exists(「testpath」),true);是測試的重點。你錯過了這個問題的重點。 – Stev0

+1

@ Stev0你應該在測試工具的構造函數中進行測試。它應該在TestMethod中。 –

+0

我把測試放在構造函數中來顯示訂單問題,這會從使用繼承的基類進行測試中提升。再次缺少重點。 – Stev0

0

您正在嘗試使用推導的方法你[TestClass]從SUT類以訪問受保護的方法。

首先:你所做的事情是否真的有必要?在您發佈的代碼中,沒有明確嘗試訪問受保護的SUT成員的測試。所以,你有可能讓事情比他們需要的更困難。

現在,如果你確實需要在這個SUT類來測試一個受保護的成員,那麼你有沒有考慮建立從SUT類繼承的類 - 一類是不[TestClass]?例如:

//RealClass.cs 
public class RealClass{ 
    public RealClass(string path){ 
     this._path = path; 
     this._InitDirectory(); 
    } 

    protected string _path; 
    protected void _InitDirectory(){ 
     //Something that requires read from path 
     File.WriteAllText(this._path + "/realData.data", "some real data that needs to be created by the class"); 
    } 
} 

// TestableRealClass.cs - Only used by the unit test 
public class TestableRealClass: RealClass { 
    public TestableRealClass(string path) : base(path) { }   

    public string Path { 
     get { 
      return _path; 
     } 
    } 

    public InitDirectory() { 
     _InitDirectory(); 
    } 
} 

//DirTest.cs 
[TestClass] 
public class DirTest { 

    [TestMethod] 
    public void TestMethod1() { 
     var testPath = @"C:\SomePath"; 

     if (!Directory.Exists(testPath)) { 
      Directory.CreateDirectory(testPath); 
     } 

     var sut = new TestableRealClass(testPath); 

     AssertThatTheFileContainsExpectedStuff(testPath); 
    } 

    [TestMethod] 
    public void TestAProtectedMember() { 
     var testPath = @"C:\SomePath"; 

     if (!Directory.Exists(testPath)) { 
      Directory.CreateDirectory(testPath); 
     } 

     var sut = new TestableRealClass(testPath); 

     Assert.AreEqual(testPath, sut.Path); 
    } 

    private void AssertThatTheFileContainsExpectedStuff(string path) { 
     // Do the assertion... 
    } 
} 

這樣,您不必擔心文本夾具的初始化順序,而且您的測試變得相當容易理解。

+0

我提供的例子本來是相當小的,是的,有必要在繼承之前測試這個類。你是正確的,沒有測試,但我試圖在沒有提供大量代碼的情況下達到目的。我看到你的邏輯,但我沒有看到它讓「測試變得相當容易理解。」我看到它讓我寫2個班而不是1個班。 – Stev0

+0

你還記得你對構造函數和靜態方法的執行順序感到困惑嗎?你的測試的讀者會受到同樣的困惑,使你的測試更難理解。至於寫兩個班而不是一個班:你絕對正確;有一個額外的類。另一方面,這種方法具有實際工作的額外好處。 – Lilshieste

+0

解決方法似乎運作良好。儘管它不是完全自包含的,但它絕不是混亂的,並且強制執行順序更合乎邏輯。我認爲從邏輯上來說,理解靜態ClassInitialize方法將在類被初始化之前調用,如果在類被銷燬之後調用清理(它就是這樣)。 – Stev0