Reply to comment

Your reply

You need to sign up / log in to reply to this comment

Existing comment

In general, it is a good introductory article but I would suggest one important thing:

Don't use ExpectedExceptionAttribute as it is not longer supported by NUnit (starting from 3.0 ). If you use ExpectedExceptionAttribute, test returns false positive if given exception is thrown from any place in the unit test, not only from a method under test.

I also have couple of other suggestions which are for a bit more advanced level but maybe still worth mentioning:

  • Test naming. Developer (and/or tester - where QA writes test cases) shall be able to get idea what are the test conditions and expected result by just reading test name.

EmailSender_SendEmail_Successfully() does not give much information about what successfully means (it doesn't throw exception? it returns boolean true?) and also what requirements arguments have to meet in order to make this method to succeed. I would suggest using fully descriptive test names, like:

 SendEmail_returns_true_when_receiverEmailAddress_is_valid_email_address_and_subject_and_body_are_non_empty_strings(). 

Following this logic, test names for negative cases could be:

SendEmail_throws_ArgumentException_when_receiverEmailAddress_is_NULL()
SendEmail_throws_ArgumentException_when_receiverEmailAddress_is_empty_string()
SendEmail_throws_ArgumentException_when_subject_is_NULL()
SendEmail_throws_ArgumentException_when_subject_is_empty_string()
etc...

Also, if test class is named EmailSenderTest (or better EmailSender_Test), meaning that EmailSender is SUT, there is no need to repeat its name in every test name. Test names can start with the name of the method tested.

  • There should be unit tests which verify that that dependencies are being called. In the case above, there shall be a unit test which verifies that SendEmail calls IEmailValidator.IsEmailValid:
SendEmail_calls_IEmailValidator_IsEmailValid()

...and also a test which verifies execution branch which throws exception:

SendEmail_throws_ArgumentException_when_IEmailValidator_IsEmailValid_returns_false()

Assuming there are unit tests covering IsEmailValid of the implementations of IEmailValidator, and with test stated above, there is no need to distinguish valid/non-valid email address in unit tests for EmailSender. Any string can be used and IEmailValidator.IsEmailValid can be mocked to always return true. We have to trust unit tests written for dependency classes and build new tests upon them. That is the reason why there is no need for test like:

SendEmail_throws_ArgumentException_when_receiverEmailAddress_is_not_valid_email_address()
  • Where test shall pass when input can be any value of a given type, that shall be explicitly stated in the test by using values made by the random value generator. In the case above, subject and body can be any non-null and non-empty strings so in the Arrange section you should assign them random string values (e.g. GUID).

Thanks for commenting

Please remember:
Be polite, helpful and keep a positive attitude
Keep it short
Use examples
Review spelling and grammar

Please avoid:
Long texts
Code that is untested
Wall of text