Geeks With Blogs

News



Add to Google

Tim Hibbard CEO for EnGraph software

I try to maintain 100% code coverage in my non-UI classes, especially my state objects that just hold data.  I recently ran into a situation that I'm having trouble writing an automated test for.  We have a ContactInformation class that holds information about how to contact a person (home phone, cell phone, email), and in that class I have a .SendEmail and .VisitWebSite methods:

public void SendEmail() { if (!string.IsNullOrEmpty(_emailAddress)) { System.Diagnostics.Process.Start("mailto:" + _emailAddress); } } public void VisitWebSite() { if (!string.IsNullOrEmpty(_webPage)) { System.Diagnostics.Process.Start(WebPage); } }

Obviously, running a unit test against these methods would open a new mail item and a web browser.  Plus the methods are void, so my test would only assert that the methods did not encounter an exception.

I'm considering changing these methods so they return a string that the consumer could shell out in the fashion that they desire.  That way, I would remove the functionality from my state object and it would be testable.

Thoughts?

 

Technorati tags: , ,
Posted on Thursday, March 29, 2007 9:27 AM .NET | Back to top


Comments on this post: Unit testing thoughts

# re: Unit testing thoughts
Requesting Gravatar...
just coded this in notepad, haven't tested for compilation:

public interface ISendEmail
{
void SendEmail(string address);
}

public class EmailSender : ISendEmail
{
public void SendEmail(string address)
{
if (!String.IsNullOrEmpty(address))
{
System.Diagnostics.Process.Start("mailto:" + address);
}
}
}

public class ContactInformation
{
private ISendEmail _sender;

public ContactInformation()
: this(new EmailSender())
{ }

public ContactInformation(ISendEmail sender)
{
if (sender == null) throw new ArgumentNullException(...);
}
}

internal class MockEmailSender : ISendEmail
{
public void SendEmail(string address)
{
_sent = (!String.IsNullOrEmpty(address));
}

public bool Sent
{
get { return _sent; }
}
private bool _sent;
}

[TestClass]
public class ContactInformationTests
{
[Test]
public void SendEmail_string_Test()
{
MockEmailSender sender = new MockEmailSender();
ContactInformation obj = new ContactInformation(sender);
// set obj state here
obj.SendEmail("alias@example.com");
Assert.IsTrue(sender.Sent);
}
}
Left by Alan Dean on Mar 29, 2007 10:50 AM

# re: Unit testing thoughts
Requesting Gravatar...
Thanks Alan. I see what you are getting at!
Left by Tim Hibbard on Mar 29, 2007 11:51 AM

# re: Unit testing thoughts
Requesting Gravatar...
I concur with alan's approach.
Left by dru on Mar 29, 2007 12:53 PM

# re: Unit testing thoughts
Requesting Gravatar...
One thing you might want to add is to have the MockEmailSender validate *more* than just looking for null or empty. You could actually validate the URI as a valid email address. This would catch errors in the code line System.Diagnostics.Process.Start("mailto:" + address); which would still not be hit by code coverage. I like to use mock objects in this way - extra validation that you might not do in the actual program but appropriate for the test objects.
Left by Bill on Mar 30, 2007 4:51 AM

# re: Unit testing thoughts
Requesting Gravatar...
[Then again, in this specific case the comment does not really apply. But the principal might.]
Left by Bill on Mar 30, 2007 4:53 AM

Your comment:
 (will show your gravatar)


Copyright © Tim Hibbard | Powered by: GeeksWithBlogs.net