在这个单元测试中是否有太多断言?
[Fact]
public void Send_sends_an_email_message() {
using (var server = new MockSmtpServer()) {
server.Start();
using (var client = new EmailClient("localhost")) {
string from = "john.doe@example.com";
IEnumerable<string> to = new[] { "jane.doe@example.com" };
string subject = "Test";
string body = "Test.";
client.Send(from, to, subject, body);
var session = server.Sessions.FirstOrDefault();
Assert.NotNull(session);
var message = session.Messages.FirstOrDefault();
Assert.NotNull(message);
Assert.NotNull(message.From);
Assert.Equal(message.From.Address, "john.doe@example.com");
Assert.NotNull(message.To);
var recipient = message.To.FirstOrDefault();
Assert.NotNull(recipient);
Assert.Equal(recipient.Address, "jane.doe@example.com");
Assert.Equal(message.Subject, "Test");
Assert.Equal(message.Body, "Test.");
}
}
}
我认为此代码不需要任何解释,但如果确实如此,请告诉我。
答案 0 :(得分:6)
我尝试保持我的UnitTests相当小,并一次测试一件事。所以我可能会将不同的部分测试到单独的测试中,例如
sendWillSendAnEmail
,fromContainsSenderAddress
,toContainsRecipientAddress
,mailBodyContainsMailMessage
,mailContainsSubject
答案 1 :(得分:6)
我觉得它太大了。
当你有一堆较小的测试时,你可以获得“缺陷本地化” - 只需运行所有测试,你就可以确切地看到问题所在。由于您拥有尽可能多的断言(并且没有断言消息),您可能必须启动调试器才能找到答案。请记住,您可能最终会有数百个(如果不是数千个)测试,并且如果其中一组测试失败,您不需要调试每个测试以查看原因。
此外,任何断言在测试早期失败意味着后续断言不会运行。当它们被分成单独的测试时,每个断言都会被检查。这是一种权衡;很多这些断言可能是相关的并且会同时失败,所以你将有五个红色测试而不是一个。但是我的前提是更多的信息更好,所以我宁愿进行这五个测试,并且知道所有五个断言都失败了。
答案 2 :(得分:4)
我发现你的断言没有特别的问题,但如果你想清理你的代码,你可以改变
var session = server.Sessions.FirstOrDefault();
Assert.NotNull(session);
到
var session = server.Sessions.First();
First()
无论如何都会抛出异常,所以只需更改代码就可以获得断言带给你的好处,而不需要代码。还有其他地方也可以进行类似的更改。
但作为一般规则,在单元测试中不要理所当然 - 这意味着很多断言!
答案 3 :(得分:2)
这取决于你所遵循的标准,但我通常会说是的,你在这个测试中得到了太多的断言。
许多人认为单个测试应该有一个断言;我认为这可能有点矫枉过正,但我确实认为对单个“功能块”进行单个单元测试是合适的。你的断言到处都是你。测试太大了;把它分成几个不同的测试。
答案 4 :(得分:1)
一般来说,断言越多越好。单元测试中常见的错误不够明确。
您的测试非常明确且可读。我特别喜欢null上的断言。这是一个很好的做法,因为它使得解释测试失败非常简单。
你可以拥有太多断言的唯一方法就是如果你多次断言完全相同的事情,你就不会这样做。
答案 5 :(得分:1)
是的,您的代码中有太多断言!而且,断言语句每个测试方法应该只有一个。使用许多断言可能是您正在测试不止一件事的代码气味。此外,有人可能会在测试中添加新断言,而不是编写另一个断言。当第一个断言失败时,你怎么能理解你的其他断言是如何完成的?
您可能还会发现这篇文章很有意思:https://timetocode.wordpress.com/2016/06/01/zen-of-unit-testing/
答案 6 :(得分:0)
我认为问题是,assert()d值是否独立变化?如果它们独立变化,那么它们应该在不同的测试中进行测试,这些测试会改变与每个断言相关的条件。
但是,如果您有一个代码路径生成包含所有这些字段的电子邮件,那么在一次测试中测试所有这些内容是合适的。
现在测试有点难以阅读。您可能希望将这些断言包装在描述性帮助器方法中。在我发现相同的辅助方法在其他地方可能有用之前,我不会打扰它。
答案 7 :(得分:0)
您的许多断言语句表明您在单元测试中拥有多少逻辑。您将不得不像常规代码一样维护您的单元测试。最好花时间进行防御性编程和合同编程,而不是代码单元测试。
答案 8 :(得分:0)
也许您可以创建一个新的Email类,在其默认构造函数中接受所有这些参数。
然后,如果用户传递了无效参数,您可以抛出异常。
在你的单元测试中
Send_sends_an_email_message
您可以添加仅检查等式的断言,而不是检查NULL。
也许您可以在一次测试中创建2封电子邮件,并为两个实例执行相等的断言。