2014-04-18 53 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