patterncsharpMinor
TDD workflow best-practices for .NET using NUnit
Viewed 0 times
workflownunitnetpracticesforusingtddbest
Problem
I'm starting to dive into TDD with NUnit and despite I've enjoyed checking some resources I've found here at stackoverflow, I often find myself not gaining good traction.
So what I'm really trying to achieve is to acquire some sort of checklist/workflow —and here's where I need you guys to help me out— or "Test Plan" that will give me decent Code Coverage.
So let's assume an ideal scenario where we could start a project from scratch with let's say a Mailer helper class that would have the following code:
(I've created the class just for the sake of aiding the question with a code sample so any criticism or advice is encouraged and will be very welcome)
Mailer.cs
```
using System.Net.Mail;
using System;
namespace Dotnet.Samples.NUnit
{
public class Mailer
{
readonly string from;
public string From { get { return from; } }
readonly string to;
public string To { get { return to; } }
readonly string subject;
public string Subject { get { return subject; } }
readonly string cc;
public string Cc { get { return cc; } }
readonly string bcc;
public string BCc { get { return bcc; } }
readonly string body;
public string Body { get { return body; } }
readonly string smtpHost;
public string SmtpHost { get { return smtpHost; } }
readonly string attach;
public string Attach { get { return Attach; } }
public Mailer(string from = null, string to = null, string body = null, string subject = null, string cc = null, string bcc = null, string smtpHost = "localhost", string attach = null)
{
this.from = from;
this.to = to;
this.subject = subject;
this.body = body;
this.cc = cc;
this.bcc = bcc;
this.smtpHost = smtpHost;
this.attach = attach;
}
public void SendMail()
{
if (string.IsNullOrEmpty(Fro
So what I'm really trying to achieve is to acquire some sort of checklist/workflow —and here's where I need you guys to help me out— or "Test Plan" that will give me decent Code Coverage.
So let's assume an ideal scenario where we could start a project from scratch with let's say a Mailer helper class that would have the following code:
(I've created the class just for the sake of aiding the question with a code sample so any criticism or advice is encouraged and will be very welcome)
Mailer.cs
```
using System.Net.Mail;
using System;
namespace Dotnet.Samples.NUnit
{
public class Mailer
{
readonly string from;
public string From { get { return from; } }
readonly string to;
public string To { get { return to; } }
readonly string subject;
public string Subject { get { return subject; } }
readonly string cc;
public string Cc { get { return cc; } }
readonly string bcc;
public string BCc { get { return bcc; } }
readonly string body;
public string Body { get { return body; } }
readonly string smtpHost;
public string SmtpHost { get { return smtpHost; } }
readonly string attach;
public string Attach { get { return Attach; } }
public Mailer(string from = null, string to = null, string body = null, string subject = null, string cc = null, string bcc = null, string smtpHost = "localhost", string attach = null)
{
this.from = from;
this.to = to;
this.subject = subject;
this.body = body;
this.cc = cc;
this.bcc = bcc;
this.smtpHost = smtpHost;
this.attach = attach;
}
public void SendMail()
{
if (string.IsNullOrEmpty(Fro
Solution
It is important to get one's mindset in a TDD mode beforehand. What I mean by this is
1) Identify the responsibility of a class - this helps in identifying the test cases.
2) Identify the interactions of the class with external dependencies - Unit testing shouldn't be testing the behaviour of the external dependency.
In this case - you have written a wrapper class around SendMail whose responsibility is to "Collect and Despatch".
I'd say SmtpClient is a dependency - you should be able to Mock it's behaviour in your test.
Mailer.cs
Testing SendMail
1) Identify the responsibility of a class - this helps in identifying the test cases.
2) Identify the interactions of the class with external dependencies - Unit testing shouldn't be testing the behaviour of the external dependency.
In this case - you have written a wrapper class around SendMail whose responsibility is to "Collect and Despatch".
I'd say SmtpClient is a dependency - you should be able to Mock it's behaviour in your test.
Mailer.cs
using System.Net.Mail;
using System;
namespace Dotnet.Samples.NUnit
{
public class Mailer
{
readonly string from;
public string From { get { return from; } }
readonly string to;
public string To { get { return to; } }
readonly string subject;
public string Subject { get { return subject; } }
readonly string cc;
public string Cc { get { return cc; } }
readonly string bcc;
public string BCc { get { return bcc; } }
readonly string body;
public string Body { get { return body; } }
readonly string smtpHost;
public string SmtpHost { get { return smtpHost; } }
readonly string attachment;
public string Attachment { get { return Attachment; } }
private SmtpClient smtpClient;
public Mailer(string from = null, string to = null, string body = null, string subject = null, string cc = null, string bcc = null, string smtpHost = "localhost", string attachment = null, SmtpClient smtpClient= new SmtpClient())
{
this.from = from;
this.to = to;
this.subject = subject;
this.body = body;
this.cc = cc;
this.bcc = bcc;
this.smtpHost = smtpHost;
this.attachment = attachment;
}
public void SendMail()
{
if (string.IsNullOrEmpty(From))
throw new ArgumentNullException("Sender e-mail address cannot be null or empty.", from);
MailMessage mail = new MailMessage();
smtpClient.Send(mail);
}
}
}Testing SendMail
[Test]
public voud ShouldCallSendOfSmtpClientWhenSendMailIsCalled
{
//Stub & Setup
var mockSmtpClient = MockRepository.GenerateMock();
var mailer = new Mailer(smtpClient: mockSmtpClient);
//Act
var message = new MailMessage();
mailer.SendMail(message);
//Assert
mockSmtpClient.AssertWasCalled(m=>m.Send(Arg.Is.Anything));
}Code Snippets
using System.Net.Mail;
using System;
namespace Dotnet.Samples.NUnit
{
public class Mailer
{
readonly string from;
public string From { get { return from; } }
readonly string to;
public string To { get { return to; } }
readonly string subject;
public string Subject { get { return subject; } }
readonly string cc;
public string Cc { get { return cc; } }
readonly string bcc;
public string BCc { get { return bcc; } }
readonly string body;
public string Body { get { return body; } }
readonly string smtpHost;
public string SmtpHost { get { return smtpHost; } }
readonly string attachment;
public string Attachment { get { return Attachment; } }
private SmtpClient smtpClient;
public Mailer(string from = null, string to = null, string body = null, string subject = null, string cc = null, string bcc = null, string smtpHost = "localhost", string attachment = null, SmtpClient smtpClient= new SmtpClient())
{
this.from = from;
this.to = to;
this.subject = subject;
this.body = body;
this.cc = cc;
this.bcc = bcc;
this.smtpHost = smtpHost;
this.attachment = attachment;
}
public void SendMail()
{
if (string.IsNullOrEmpty(From))
throw new ArgumentNullException("Sender e-mail address cannot be null or empty.", from);
MailMessage mail = new MailMessage();
smtpClient.Send(mail);
}
}
}[Test]
public voud ShouldCallSendOfSmtpClientWhenSendMailIsCalled
{
//Stub & Setup
var mockSmtpClient = MockRepository.GenerateMock<SmtpClient>();
var mailer = new Mailer(smtpClient: mockSmtpClient);
//Act
var message = new MailMessage();
mailer.SendMail(message);
//Assert
mockSmtpClient.AssertWasCalled(m=>m.Send(Arg<MailMessage>.Is.Anything));
}Context
StackExchange Code Review Q#2699, answer score: 4
Revisions (0)
No revisions yet.