我正在尝试在编写单元测试时遵循Arrange-Act-Assert模式,我到了一个地方,我很困惑哪种方法会更好。我正在使用xUnit,我的第一个问题是:
//Arrange
int key = 1;
string value = "X";
//Act
board.Add(key, value);
var result = Assert.Throws<ArgumentException>(() => board.Add(key, value));
//Assert
Assert.IsType<ArgumentException>(result);
我的第二种方法是:
int key = 1;
string value = "X";
board.Add(key, value);
Assert.Throws<ArgumentException>(() => board.Add(key, value));
这是一种更好的方法吗?
编辑: 在wp.me/p4f69l-3z上发表了关于此的博客
答案 0 :(得分:5)
您的第一次.Add
电话应该是安排的一部分。将其视为行为的前提条件/设置。除此之外,您可以在Action
中包含 act 以使其更好地阅读:
//Arrange
int key = 1;
string value = "X";
board.Add(key, value);
//Act
Action addingSameKeySecondTime = () => board.Add(key, value);
//Assert
Assert.Throws<ArgumentException>(addingSameKeySecondTime)
评论中提到的FluentAssertions库使得这样的断言更加类似于句子:
int key = 1;
string value = "X";
board.Add(key, value);
Action addingSameKeySecondTime = () => board.Add(key, value);
addingSameKeySecondTime.ShouldThrow<ArgumentException>();
答案 1 :(得分:1)
对我来说,源代码应该是自描述的,因此AAA注释更像是解决方法,可能无法提供足够的灵活性。 检查此库:Heleonix.Testing 您可以在Given / When / Then和AAA表单中编写JavaScript Jasmine / Jest样式中的测试。
答案 2 :(得分:0)
我会说你的第二个例子更好。 Assert.Throws将通过/未通过测试,因此没有理由得到它的结果并断言。当我写'将抛出'测试时,我将它保持在一两行:
[Test]
public void SomeMethod_NullSomething_ShouldThrow() {
var something = MakeTarget();
Assert.Throws<ArgumentNullException>(() => something.SomeMethod(null));
}
答案 3 :(得分:0)
实际上断言异常没有好的答案......就像测试事件一样,除了它们会中断代码流。假设你要测试add事件(我正在使用NUnit):
// Arrange
int key = 1;
var eventFired = false;
board.Added += (boardItem) => {
eventFired = boardItem.key == key;
};
// Act
board.Add(key, "X");
// Assert
Assert.That(eventFired, Is.True);
测试异常时也是如此:
// Arrange
int key = 1;
var exceptionRaised = false;
board.Add(key, "X");
// Act
try {
board.Add(key, "X");
}
catch(InvalidOperationException ex) {
exceptionRaised = true;
}
// Assert
Assert.That(exceptionRaised, Is.True);
所以Assert.Throws可以用来方便,但它不适合AAA风格。但是请记住,AAA并不是强制要求编写好的测试,最重要的是让测试易于理解。
答案 4 :(得分:0)
我通常采用以下方法
// Arrange
int key = 1;
string value = "X";
board.Add(key, value);
// Act & Assert
Assert.Throws<ArgumentException>(() => board.Add(key, value));
这是ASP.NET MVC中采用的方法(例如https://aspnetwebstack.codeplex.com/SourceControl/latest#test/Common/PrefixContainerTest.cs)