这个问题涉及使用MSTest在Visual Studio中进行单元测试(这很重要,因为MSTest的execution order)。标记为[TestInitialize]的方法和测试类构造函数都将在每个测试方法之前运行。
所以,问题是,你在这些领域中倾向于做什么?你是否避免在两者中进行某些活动?你的理由是什么:风格,技术,迷信?
答案 0 :(得分:49)
构造函数只是该语言提供的结构。每个测试框架似乎都有自己的受控生命周期“初始化”。你可能只会使用构造函数来改变你的本地人。
MSTest:每个TestMethod
都会获得一个测试类的全新实例。这可能是唯一可以在构造函数,初始化程序或测试方法中改变局部变量并且不影响其他测试方法的情况。
public class TestsForWhatever
{
public TestsForWhatever()
{
// You get one of these per test method, yay!
}
[TestInitialize]
public void Initialize()
{
// and one of these too!
}
[TestMethod]
public void AssertItDoesSomething() { }
[TestMethod]
public void AssertItDoesSomethingElse() { }
}
MSpec:您的所有断言(Establish
)只能获得一个Because
和It
。所以,不要在断言中改变你的本地人。并且不依赖于基本上下文中的本地变异(如果使用它们)。
[Subject(typeof(Whatever))]
public class When_doing_whatever
{
Establish context = () =>
{
// one of these for all your Its
};
Because of = () => _subject.DoWhatever();
It should_do_something;
It should_do_something_else;
}
答案 1 :(得分:17)
以下是我在TestInitialize中找到的一些优点。
答案 2 :(得分:15)
使用TestInitialize()或ClassInitialize()而不是测试类实例或静态构造函数的主要优点是它的显式特性。它清楚地表明您在测试之前正在进行一些设置。持续这样做可以长期提高可维护性。
答案 3 :(得分:4)
我更喜欢使用[TestInitialize]
方法来执行被测对象及其参数的实例化。如果需要实例化测试基类(通常是我创建或刷新存储库的位置等),我只在构造函数中执行工作。这有助于我将测试框架代码和测试代码在逻辑上和物理上分开。
答案 4 :(得分:3)
FWIW我认为“类构造函数”是指instance constructor(不是static constructor)。
我相信您提出的同样问题同样可以询问静态构造函数与ClassInitialize ...
答案 5 :(得分:1)
您测试的对象不需要在[TestInitialize]方法中实例化。您可以在测试方法[Test]中测试对象的构造函数。
[TestInitialize]中的对象可以是设置持久存储或准备测试对象将在测试中使用的值。
答案 6 :(得分:1)
我说使用构造函数,除非你需要readonly
。
答案 7 :(得分:0)
这取决于场景。如果你有一个测试类,并且出于一些奇怪的原因,如果你需要在另一个测试类上创建它的实例,你将需要使用构造函数。
否则测试初始化更符合概念。首先,与上面写的相同的原因,第二个MS可以在该属性上引入更多的功能,你将从中受益,你将坚持使用构造函数。
答案 8 :(得分:0)
我知道我参加晚会很晚,但是有了async
,这就是[TestInitialize]
的另一个原因(当问这个问题时这个问题没有延续)。允许您执行async
操作来设置(例如加载文件),这在构造函数中是不可能的:
private string approver;
[TestInitialize]
public async Task Initialize()
{
approver = File.ReadAllTextAsync("approver.json");
}
答案 9 :(得分:0)
我希望有人仍然需要。这是我的解决方案,如何对类构造函数进行单元测试。 我正在单元测试类服务中,如果debuggingService为null,则会引发异常。
DebuggingStepTests类构造函数
private readonly IDebuggingService debuggingService;
public string StepName { get; set; }
public DebuggingStep(IDebuggingService _debuggingService)
{
_log.Starting();
StepName = "DebuggingStep";
debuggingService = _debuggingService
?? throw new ArgumentException("DebuggingStep init failure due to => IDebuggingService null");
}
UnitTests看起来像这样
[Fact]
public void TestDebuggingStepConstructorWhen_InitServiceIsNull_ResultArgumentException()
{
//Arrange
var arrange = new Action(() =>
{
new DebuggingStep(null);
});
//Act
//Arrange
Assert.Throws<ArgumentException>(arrange);
}
希望这对某人有帮助