Friday, January 22, 2016

When a stub acts like a ref variable in a C# unit test, the way any reference type will even inexplicitly, it's pretty darn awesome!

Let's test this method!

using System;
using Whatever.Security.Web.Core;
using Whatever.Security.Web.Core.Interfaces;
using SomethingErOther.Core.Interfaces;
namespace SomethingErOther.Core
{
   public static class HtmlEmailFacilitator
   {
      public static void PrepareAndSendEmail(IHtmlEmailUtility htmlEmailUtility, User
            user, IRepository repository)
      {
         string emailHeader = user.Group.EmailTemplateHeader;
         string emailBody = user.Group.EmailTemplate;
         if (String.IsNullOrWhiteSpace(emailHeader) ||
               String.IsNullOrWhiteSpace(emailBody))
         {
            DIProperties properties = repository.GetProperties();
            if (String.IsNullOrWhiteSpace(emailHeader)) emailHeader =
                  properties.DefaultEmailTriggerSubject;
            if (String.IsNullOrWhiteSpace(emailBody)) emailBody =
                  properties.DefaultEmailTriggerBody;
         }
         htmlEmailUtility.SendEmail(emailHeader, emailBody, user.Email);
      }
   }
}

 
 

Wait a minute, how can we possibly test a void method? It doesn't return anything for us to do an Assert against, right? Well, I found a way today. Consider this stub for IHtmlEmailUtility:

using SomethingErOther.Core.Interfaces;
namespace SomethingErOther.Core.Test.Stubs
{
   public class HtmlEmailUtilityStub : IHtmlEmailUtility
   {
      public string EmailHeaderHandedIn { get; set; }
      public string EmailBodyHandedIn { get; set; }
      public string ToAddressHandedIn { get; set; }
      
      public void SendEmail(string emailHeader, string emailBody, string toAddress)
      {
         EmailHeaderHandedIn = emailHeader;
         EmailBodyHandedIn = emailBody;
         ToAddressHandedIn = toAddress;
      }
   }
}

 
 

It can dip into our method, do its job, and then dip back out carrying some acquired state from its journey. We can assert against the acquired state. Behold:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using NSubstitute;
using Whatever.Security.Web.Core;
using Whatever.Security.Web.Core.Interfaces;
using SomethingErOther.Core.Test.Stubs;
namespace SomethingErOther.Core.Test
{
   [TestClass]
   public class HtmlEmailFacilitatorTests
   {
      private User _user;
      private IRepository _repository;
      
      [TestInitialize]
      public void Prepare()
      {
         _user = new User();
         _user.Email = "me@example.com";
         _user.Group = new Group();
         using (_repository = Substitute.For<IRepository>())
         {
            _repository.GetProperties().Returns(new DIProperties()
            {
               DefaultEmailTriggerSubject = "Welcome to Corelas!",
               DefaultEmailTriggerBody = "It's a dirty place."
            });
         }
      }
      
      [TestMethod]
      public void HtmlEmailFacilitator_happy_pass_test()
      {
         _user.Group.EmailTemplateHeader = "Welcome to Austin!";
         _user.Group.EmailTemplate = "It's a fun place.";
         HtmlEmailUtilityStub stub = new HtmlEmailUtilityStub();
         HtmlEmailFacilitator.PrepareAndSendEmail(stub, _user, null);
         Assert.AreEqual(stub.EmailHeaderHandedIn, "Welcome to Austin!");
         Assert.AreEqual(stub.EmailBodyHandedIn, "It's a fun place.");
         Assert.AreEqual(stub.ToAddressHandedIn, "me@example.com");
      }
      
      [TestMethod]
      public void HtmlEmailFacilitator_lack_of_body_of_email_is_handled_as_expected()
      {
         HtmlEmailUtilityStub stub = new HtmlEmailUtilityStub();
         _user.Group.EmailTemplateHeader = "Welcome to Houston!";
         HtmlEmailFacilitator.PrepareAndSendEmail(stub, _user, _repository);
         Assert.AreEqual(stub.EmailHeaderHandedIn, "Welcome to Houston!");
         Assert.AreEqual(stub.EmailBodyHandedIn, "It's a dirty place.");
         Assert.AreEqual(stub.ToAddressHandedIn, "me@example.com");
      }
      
      [TestMethod]
      public void HtmlEmailFacilitator_lack_of_subject_line_is_handled_as_expected()
      {
         HtmlEmailUtilityStub stub = new HtmlEmailUtilityStub();
         _user.Group.EmailTemplate = "It's an angry place.";
         HtmlEmailFacilitator.PrepareAndSendEmail(stub, _user, _repository);
         Assert.AreEqual(stub.EmailHeaderHandedIn, "Welcome to Corelas!");
         Assert.AreEqual(stub.EmailBodyHandedIn, "It's an angry place.");
         Assert.AreEqual(stub.ToAddressHandedIn, "me@example.com");
      }
      
      [TestMethod]
      public void HtmlEmailFacilitator_unprepared_Group_at_User_behaves_as_expected()
      {
         HtmlEmailUtilityStub stub = new HtmlEmailUtilityStub();
         HtmlEmailFacilitator.PrepareAndSendEmail(stub, _user, _repository);
         Assert.AreEqual(stub.EmailHeaderHandedIn, "Welcome to Corelas!");
         Assert.AreEqual(stub.EmailBodyHandedIn, "It's a dirty place.");
         Assert.AreEqual(stub.ToAddressHandedIn, "me@example.com");
      }
   }
}

No comments:

Post a Comment