断言从模拟对象构造函数抛出的异常

Nor*_*ren 10 c# tdd nunit unit-testing moq

假设:VS2010,.NET 4,C#,NUnit,Moq

我是TDD的新手,在完成一个项目时遇到了这个问题.

鉴于课程:

public abstract class MyFileType
{                
    public MyFileType(String fullPathToFile)
    {
        if (!File.Exists(fullPathToFile))
        {
            throw new FileNotFoundException();
        }

        // method continues

    }
}
Run Code Online (Sandbox Code Playgroud)

我试图使用该方法测试它:

[Test]
[ExpectedException(typeof(System.IO.FileNotFoundException))]
public void MyFileType_CreationWithNonexistingPath_ExceptionThrown()
{
    String nonexistingPath = "C:\\does\\not\\exist\\file.ext";
    var mock = new Mock<MyFileType>(nonexistingPath);
}
Run Code Online (Sandbox Code Playgroud)

测试失败,NUnit报告从未抛出异常.

我确实在NUnit文档中找到了一个关于断言与异常断言的部分,但这些示例似乎并不像我想要做的那样.我仍然开始使用NUnit和Moq,所以我可能会以错误的方式解决这个问题.

更新:

为了帮助阐明此示例使用抽象类的原因,它是一系列文件类型的基类,其中只有子类型之间的数据加载和处理会有所不同.我最初的想法是将open/setup的逻辑放入基类中,因为它对所有类型都是相同的.

Dan*_*ant 5

在引用mock.Object之前,不会调用构造函数.那应该会引发你期待的异常.

另一方面,让构造函数抛出除使用异常之外的异常(例如各种ArgumentException派生词)通常是不好的做法.大多数开发人员不希望"new"抛出异常,除非他们做了非常错误的事情; 不存在的文件是可以在程序控制之外合法发生的异常类型,因此您可能希望将其设置为静态工厂方法,而不是"FromFileName".编辑:鉴于这是一个基类构造函数,这也不是真的适用,所以你可能想考虑哪里是进行此检查的最佳位置.毕竟,文件可能在任何时候停止存在,因此检查构造函数甚至没有意义(无论如何,您都需要检查所有相关方法.)


leo*_*eon 3

如果您必须让该类成为抽象类,那么我们应该按照其本来的样子实现它(简单):MSDN:一个抽象类

因此,(与 alexanderb)同意这里可能不需要模拟,并且同意 Stecy 在 .Throws NUnit Assert 扩展上的观点,您可以在测试中创建一个调用基类的类,如下所示:

using System;
using System.IO;

namespace fileFotFoundException {
    public abstract class MyFile {

        protected MyFile(String fullPathToFile) {
            if (!File.Exists(fullPathToFile)) throw new FileNotFoundException();
        }
    }
}

namespace fileFotFoundExceptionTests {
    using fileFotFoundException;
    using NUnit.Framework;

    public class SubClass : MyFile {
        public SubClass(String fullPathToFile) : base(fullPathToFile) {
            // If we have to have it as an abstract class...
        }
    }

    [TestFixture]
    public class MyFileTests {

        [Test]
        public void MyFile_CreationWithNonexistingPath_ExceptionThrown() {
            const string nonExistingPath = "C:\\does\\not\\exist\\file.ext";

            Assert.Throws<FileNotFoundException>(() => new SubClass(nonExistingPath));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)