This Saturday like the last two I planned to work on my wooden terrace, but with the weather we have for this year’s spring, it was almost impossible. So I replaced that with some development.

I am using Rhino.Mocks as mock object framework and went to the following solution to mock SmtpClient.

Capabilities of Rhino.Mock are to mock interfaces, delegates and virtual methods of classes!

My goal was to test my MailService class which use SmtpClient and in particular the method SendAsync, which is not a virtual method. SmtpClient inherit from System.Object so no way to use an interface for the unit test.

Next step was then to make an interface, ISmtpClient, out of the SmtpClient of the .NET Framework using Reflector for .Net. Then I modified the dependency of my MailService class from SmtpClient of the .NET framework to my interface ISmtpClient.

using System.Net;

using System.Net.Mail;

using System.Security.Cryptography.X509Certificates;

using System.Security.Permissions;

namespace TechHeadBrothers.Portal.Services.Mail

{

<span style="color: #cc7832">public</span> <span style="color: #cc7832">interface</span> <span style="color: #6897bb">ISmtpClient</span>

{

    <span style="color: gray">// Events</span>

    <span style="color: #cc7832">event</span> <span style="color: #6897bb">SendCompletedEventHandler</span> SendCompleted;

    <span style="color: gray">// Properties</span>

    <span style="color: #ffc66d">X509CertificateCollection</span> ClientCertificates { <span style="color: #cc7832">get</span>; }

    <span style="color: #6897bb">ICredentialsByHost</span> Credentials { <span style="color: #cc7832">get</span>; <span style="color: #cc7832">set</span>; }

    <span style="color: #6897bb">SmtpDeliveryMethod</span> DeliveryMethod { <span style="color: #cc7832">get</span>; <span style="color: #cc7832">set</span>; }

    <span style="color: #cc7832">bool</span> EnableSsl { <span style="color: #cc7832">get</span>; <span style="color: #cc7832">set</span>; }

    <span style="color: #cc7832">string</span> Host { <span style="color: #cc7832">get</span>; <span style="color: #cc7832">set</span>; }

    <span style="color: #cc7832">string</span> PickupDirectoryLocation { <span style="color: #cc7832">get</span>; <span style="color: #cc7832">set</span>; }

    <span style="color: #cc7832">int</span> Port { <span style="color: #cc7832">get</span>; <span style="color: #cc7832">set</span>; }

    <span style="color: #ffc66d">ServicePoint</span> ServicePoint { <span style="color: #cc7832">get</span>; }

    <span style="color: #cc7832">int</span> Timeout { <span style="color: #cc7832">get</span>; <span style="color: #cc7832">set</span>; }

    <span style="color: #cc7832">bool</span> UseDefaultCredentials { <span style="color: #cc7832">get</span>; <span style="color: #cc7832">set</span>; }

    <span style="color: gray">// Methods</span>

    <span style="color: #cc7832">void</span> Send(<span style="color: #ffc66d">MailMessage</span> message);

    <span style="color: #cc7832">void</span> Send(<span style="color: #cc7832">string</span> from, <span style="color: #cc7832">string</span> recipients, <span style="color: #cc7832">string</span> subject, <span style="color: #cc7832">string</span> body);

    [<span style="color: #ffc66d">HostProtection</span>(<span style="color: #6897bb">SecurityAction</span><span style="font-weight: normal">.LinkDemand, ExternalThreading = </span><span style="color: #cc7832">true</span>)]

    <span style="color: #cc7832">void</span> SendAsync(<span style="color: #ffc66d">MailMessage</span> message, <span style="color: #cc7832">object</span> userToken);

    [<span style="color: #ffc66d">HostProtection</span>(<span style="color: #6897bb">SecurityAction</span><span style="font-weight: normal">.LinkDemand, ExternalThreading = </span><span style="color: #cc7832">true</span>)]

    <span style="color: #cc7832">void</span> SendAsync(<span style="color: #cc7832">string</span> from, <span style="color: #cc7832">string</span> recipients, <span style="color: #cc7832">string</span> subject, <span style="color: #cc7832">string</span> body, <span style="color: #cc7832">object</span> userToken);

    <span style="color: #cc7832">void</span> SendAsyncCancel();

}

}

Then I wrote the class SmtpClientProxy. It is based on the design pattern Proxy. So it basically maintains a reference, and controls access, to the real SmtpClient so it can be used in place of the real SmtpClient.

namespace TechHeadBrothers.Portal.Services.Mail

{

<span style="color: #cc7832">public</span> <span style="color: #cc7832">class</span> <span style="color: #ffc66d">SmtpClientProxy</span> : <span style="color: #6897bb">ISmtpClient</span>

{

    <span style="color: #cc7832">private</span> <span style="color: #cc7832">readonly</span> <span style="color: #ffc66d">SmtpClient</span> smtpClient;

    <span style="color: #cc7832">public</span> SmtpClientProxy()

    {

        smtpClient = <span style="color: #cc7832">new</span> <span style="color: #ffc66d">SmtpClient</span>();

        smtpClient.SendCompleted += smtpClient_SendCompleted;

    }

#region ISmtpClient Members

<span style="color: #cc7832">public</span> <span style="color: #cc7832">event</span> <span style="color: #6897bb">SendCompletedEventHandler</span> SendCompleted;

<span style="color: #cc7832">public</span> <span style="color: #ffc66d">X509CertificateCollection</span> ClientCertificates

{

    <span style="color: #cc7832">get</span> { <span style="color: #cc7832">return</span> smtpClient.ClientCertificates; }

}

<span style="color: #cc7832">public</span> <span style="color: #6897bb">ICredentialsByHost</span> Credentials

{

    <span style="color: #cc7832">get</span> { <span style="color: #cc7832">return</span> smtpClient.Credentials; }

    <span style="color: #cc7832">set</span> { smtpClient.Credentials = <span style="color: #cc7832">value</span>; }

}

Finally my MailService class with the dependency injection of ISmtpClient interface and a default constructor using my SmtpClientProxy :

namespace TechHeadBrothers.Portal.Services.Mail

{

<span style="color: gray">///</span><span style="color: green"> </span><span style="color: gray"><summary></span>

<span style="color: gray">///</span><span style="color: green"> Service to deliver Emails</span>

<span style="color: gray">///</span><span style="color: green"> </span><span style="color: gray"></summary></span>

<span style="color: #cc7832">public</span> <span style="color: #cc7832">class</span> <span style="color: #ffc66d">MailService</span> : <span style="color: #6897bb">IMailService</span>

{

    <span style="color: #cc7832">private</span> <span style="color: #cc7832">readonly</span> <span style="color: #6897bb">ISmtpClient</span> smtpClient;

    <span style="color: #cc7832">public</span> MailService() : <span style="color: #cc7832">this</span>(<span style="color: #cc7832">new</span> <span style="color: #ffc66d">SmtpClientProxy</span>())

    {

    }

    <span style="color: #cc7832">public</span> MailService(<span style="color: #6897bb">ISmtpClient</span> smtpClient)

    {

        <span style="color: #cc7832">this</span><span style="font-weight: normal">.smtpClient = smtpClient;</span>

    }

In my unit test I will use the constructor in which I can specify the mock of ISmtpClient, otherwise I will use the default constructor.

So that was for the first issue; having the possibility to mock SmtpClient. Now you certainly have realized the second issue that popped up. In my ISmtpClient I have one event:

<span style="color: #cc7832">public</span> <span style="color: #cc7832">interface</span> <span style="color: #6897bb">ISmtpClient</span>

{

    <span style="color: gray">// Events</span>

    <span style="color: #cc7832">event</span> <span style="color: #6897bb">SendCompletedEventHandler</span> SendCompleted;

This event is for sure also in my proxy class, SmtpClientProxy as it inherit form ISmtpClient. In the constructor of SmtpClientProxy I add an event handler on the SendCompleted event of the SmtpClient. This event handler just fires the event exposed by the proxy class, so that I can have an event handler in MailService class to handle the SendComplete event.

<span style="color: #cc7832">private</span> <span style="color: #cc7832">void</span> smtpClient_SendCompleted(<span style="color: #cc7832">object</span> sender, <span style="color: #ffc66d">AsyncCompletedEventArgs</span> e)

{

    <span style="color: #cc7832">if</span> (SendCompleted != <span style="color: #cc7832">null</span>)

        SendCompleted(sender, e);

}

Nothing really special. But now the question rise! I need to mock ISmtpClient in my unit test. But my MailService SendMailMessage method call the SmtpClient.SendAsync method and also add an event handler to SmtpClient.SendCompleted event.

<span style="color: gray">///</span><span style="color: green"> </span><span style="color: gray"><summary></span>

<span style="color: gray">///</span><span style="color: green"> Sends a MailMessage object using the SMTP settings.</span>

<span style="color: gray">///</span><span style="color: green"> </span><span style="color: gray"></summary></span>

<span style="color: gray">///</span><span style="color: green"> </span><span style="color: gray"><param name="mailMessage"></span><span style="color: green">Email message to be sent</span><span style="color: gray"></param></span>

<span style="color: #cc7832">public</span> <span style="color: #cc7832">void</span> SendMailMessage(<span style="color: #ffc66d">MailMessage</span> mailMessage)

{

    <span style="color: #cc7832">try</span>

    {

        mailMessage.IsBodyHtml = <span style="color: #cc7832">true</span>;

        mailMessage.BodyEncoding = <span style="color: #ffc66d">Encoding</span><span style="font-weight: normal">.UTF8;</span>

        <span style="color: #cc7832">this</span><span style="font-weight: normal">.message = mailMessage;</span>

        smtpClient.SendCompleted += smtpClient_SendCompleted;

        smtpClient.SendAsync(mailMessage, <span style="color: #cc7832">null</span>);

    }

    <span style="color: #cc7832">catch</span> (<span style="color: #ffc66d">SmtpException</span>)

    {

        <span style="color: #cc7832">this</span><span style="font-weight: normal">.OnEmailFailed(mailMessage);</span>

    }

}

<span style="color: #cc7832">private</span> <span style="color: #cc7832">void</span> smtpClient_SendCompleted(<span style="color: #cc7832">object</span> sender, <span style="color: #ffc66d">AsyncCompletedEventArgs</span> e)

{

    <span style="color: #cc7832">this</span><span style="font-weight: normal">.OnEmailSent(message);</span>

}

In my mock then I need to have the same thing happening, even if I mock the interface ISmtpClient.

Here is the solution I came to:

namespace TechHeadBrothers.Portal.Services.Tests.Mail

{

[<span style="color: #ffc66d">TestFixture</span>]

<span style="color: #cc7832">public</span> <span style="color: #cc7832">class</span> <span style="color: #ffc66d">MailServiceTest</span>

{

#region Setup/Teardown

[<span style="color: #ffc66d">SetUp</span>]

<span style="color: #cc7832">public</span> <span style="color: #cc7832">void</span> SetUp()

{

    mocks = <span style="color: #cc7832">new</span> <span style="color: #ffc66d">MockRepository</span>();

}

#endregion

    <span style="color: #cc7832">private</span> <span style="color: #ffc66d">MockRepository</span> mocks;

    [<span style="color: #ffc66d">Test</span>]

    <span style="color: #cc7832">public</span> <span style="color: #cc7832">void</span> SendMailMessageRaiseEmailSentEvent()

    {

        <span style="color: #cc7832">bool</span> emailSentRaised = <span style="color: #cc7832">false</span>;

        <span style="color: #cc7832">var</span> message = <span style="color: #cc7832">new</span> <span style="color: #ffc66d">MailMessage</span>(<span style="color: #a5c25c">"lk@test.com"</span>, <span style="color: #a5c25c">"mk@test.com"</span>);

        <span style="color: #cc7832">var</span> smtpClient = mocks.Stub<<span style="color: #6897bb">ISmtpClient</span><span style="font-weight: normal">>();</span>

        <span style="color: #cc7832">var</span> mailService = <span style="color: #cc7832">new</span> <span style="color: #ffc66d">MailService</span>(smtpClient);

        mailService.EmailSent += ((sender, e) => { emailSentRaised = <span style="color: #cc7832">true</span>; });

        <span style="color: #cc7832">using</span> (mocks.Record())

        {

            <span style="color: #cc7832">var</span> raiser = <span style="color: #ffc66d">Expect</span><span style="font-weight: normal">.Call(() => smtpClient.SendCompleted += </span><span style="color: #cc7832">null</span>)

                               .IgnoreArguments().GetEventRaiser();

            <span style="color: #ffc66d">Expect</span><span style="font-weight: normal">.Call(() => smtpClient.SendAsync(message, </span><span style="color: #cc7832">null</span>))

                  .Do((<span style="color: #6897bb">Action</span><span style="font-weight: normal"><</span><span style="color: #ffc66d">MailMessage</span>, <span style="color: #cc7832">object</span><span style="font-weight: normal">>) ((arg1, arg2) => raiser.Raise(message, </span><span style="color: #cc7832">null</span>)));

        }

        <span style="color: #cc7832">using</span> (mocks.Playback())

        {

            mailService.SendMailMessage(message);

            <span style="color: #ffc66d">Assert</span><span style="font-weight: normal">.That(emailSentRaised, </span><span style="color: #ffc66d">Is</span><span style="font-weight: normal">.EqualTo(</span><span style="color: #cc7832">true</span>));

        }

    }

}

}

I create a mock of the interface ISmtpClient. Then I inject this mock into my MailService class. I create a event handler for my MailService.EmailSent event using a lambda. This lambda, if called, will change the boolean value emailSentRaised from false to true. This exactly what I want to test in that unit test; that the EmailSent event is raised.

Then I get raiser object, a Rhino Mock IEventRaiser, from smtpClient.SendCompleted event.

Finally I set an expectation on smtpClient.SendAsync method adding a Do() handler+Handler.ashx) that will raise the SendCompleted event.

Last point is using the mailService object, calling the SendMailMessage method and asserting that my boolean emailSentRaised went from false to true.

And here is the result in ReSharper Unit Test Session window. Green!

Update: By the way, I forgot to add a link to a post from Phil HaackUsing Rhino Mocks To Unit Test Events on Interfaces“ and another link to a post from Jean-Paul S. BoodhooRaising events (from a mock) using Rhino Mocks“. To great post to read!