Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there too many asserts in this unit test?

Are there too many asserts in this one unit test?

[Fact]
public void Send_sends_an_email_message() {
    using (var server = new MockSmtpServer()) {
        server.Start();
        using (var client = new EmailClient("localhost")) {
            string from = "[email protected]";
            IEnumerable<string> to = new[] { "[email protected]" };
            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, "[email protected]");
            Assert.NotNull(message.To);
            var recipient = message.To.FirstOrDefault();
            Assert.NotNull(recipient);
            Assert.Equal(recipient.Address, "[email protected]");
            Assert.Equal(message.Subject, "Test");
            Assert.Equal(message.Body, "Test.");
        }
    }
}

I don't think this code requires any explanation, but if it does please let me know.

like image 686
Arlen Avatar asked Nov 15 '10 20:11

Arlen


2 Answers

I try to keep my UnitTests fairly small and test one thing at a time. So I'd likely make testing distinct parts into separate tests, e.g.

  • sendWillSendAnEmail,
  • fromContainsSenderAddress,
  • toContainsRecipientAddress,
  • mailBodyContainsMailMessage,
  • mailContainsSubject
like image 61
Gordon Avatar answered Oct 11 '22 10:10

Gordon


I think it's too large.

When you have a bunch of smaller tests, you can get "defect localization" - just by running all the tests, you can see exactly where a problem is. With as many asserts as you currently have (and no assert messages) you'd probably have to launch a debugger to find out. Remember that you probably will end up having hundreds if not thousands of tests, and if a bunch of them are failing, you don't want to have to debug each one to see why.

Also, any assert failing early in the test means the later asserts are not run. When they're separated into individual tests, every assert is checked. This is sort of a trade-off; a lot of those asserts probably are related and will fail at the same time, so you'll have five red tests instead of one. But I work from the premise that more information is better, so I would rather have those five tests and know that all five asserts failed.

like image 24
Paul Phillips Avatar answered Oct 11 '22 10:10

Paul Phillips