Today I was facing the following issue. I have an indexing system (read more here, here and here) using Lucene.Net that is working quite good. The drawback of the current implementation was that I couldn’t filter any to be indexed property decorated with the attribute. For example if I had a string property of my domain holding HTML, I wasn’t able to remove the HTML out of the string before indexing it.
I scratch my head some time, and finally came to a pragmatic solution.
For this pragmatic solution I used meta information in the name of the attribute. So the attribute decorate my code with a meta information and the name of the attribute contains by itself also meta information. This means that I enforce some rules in the naming of the attribute.
For example the first rule is the following, if the name of the attribute contains Html in whatever form, uppercase, lowercase, etc. the framework will realize that the property contains Html and that it needs to remove the Html tags out of the string on decode it.
If none of the naming rules match then it will use the content of the property directly.
So as a user of the indexing framework, I write one attribute named HTMLSearchableAttribute and decorate my properties and then the framework will clean automatically this string property before indexing the cleaned content with Lucene.Net.
Today working on the development of a website I had the following user story to develop “As an author I want to be able to add a lightbox/darkbox around my content in Live Writer”.
First of all I updated my version of Windows Live Writer to the latest CTP version. You can download it from here: Technical Preview: Now Available for Download! Nice work Joe, it is quite stable and look really nice.
Then I needed to address this user story. To do so I thought to develop my own Live Writer plugin but with some research led me to a FANTASTIC plugin called “Dynamic Template Plugin for Windows Live Writer” and by whom, you guessed, Joe. Great work!
With this plugin I was able to implement in a very user friendly way, the needed insertion of my light and dark boxes. No an author is two click away from having it boxes on the website. Nice, really nice.
But wait this plugin can do much more than templating!
Check all videos available! Watch Example 1, Watch Example 2, Watch Example 3, Watch Example 4, Watch Example 5.
Here is the result. On the left, what you see in live writer, on the right what you see on the website.
I love Live Writer! When the pages editing will evolve it will be the must for CMS.
JetBrains has released their ultimate Visual Studio plugin, ReSharper 4.0.
This much-anticipated productivity tool includes many new features and improvements.
It supports C# 3.0 and LINQ, plugs nicely into Visual Studio 2008 and 2005 and also support VB.NET.
It includes:
- Full Support for C# 3.0 and LINQ; Full Edition and C# Edition provide comprehensive support for C# 3.0, including LINQ, implicitly typed locals and arrays, extension methods, automatic properties, lambda expressions, object & collection initializers, anonymous types, expression trees, and partial methods
- Comprehensive Insight into .NET Framework
- Solution-Wide Analysis, which looks for erroneous C# code in your whole solution on-the-fly, without compiling it first
- Code Cleanup, flexible code compliance and formatting tool bringing together a dozen of ReSharper features. In addition to fine-tuning formatting style to use, you can opt to arrange 'this' qualifier, remove code redundancies, convert properties with backup fields to auto-properties, make fields read-only if possible, optimize using directives, shorten qualified references, update file header, replace explicit types with vars, and revamp your C# code with many more settings
- New Refactorings
- Convert Static to Extension Method
- Convert Extension Method to Plain Static
- Convert Property to Auto-Property
- Convert Anonymous to Named Type
- Inline Method
- Convert Method to Indexer (to Default Property in VB.NET)
- Convert Indexer (Default Property in VB.NET) to Method
- Multiple New Productivity Features
- Complete statement; inserts necessary syntax elements (braces, semicolons etc.) and gets you to the position to start the next statement, saving you from excessive juggling with the caret.
- CamelHumps in Code Completion, allowing you to complete any symbol by entering only its uppercase characters.
- Live Templates Editor & Manager, rejuvenated set of user interface items for viewing, managing, and editing all three types of templates — Live Templates, Surround With Templates, and File Templates.
- Recent Edits, drop-down list similar to existing Go To features that shows files and symbols that you recently modified.
- Smoother Interaction with Visual Studio Ecosystem
- ASP.NET Speedup; significantly speed-up the analysis of ASP.NET pages
You might read more details about all new features or the full list of features.
I recommend printing the keyboards shortcuts available in ReSharper 2.x / IDEA scheme and Visual Studio scheme.
You might also be interested by all the ReSharper’s plugins available: Gallio, RGreatEx, Agent Smith 1.1.8, Agent Johnson, ARP Another ReSharper Plugin, NHibernate Plugin 1.0, NSpecify, Scout plugin, xUnit.net 1.0
Finally you can download a free 30-day trial version of ReSharper 4.0. Go download it, it is just a must (at least for me and some others ;)!
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
{
public interface ISmtpClient
{
// Events
event SendCompletedEventHandler SendCompleted;
// Properties
X509CertificateCollection ClientCertificates { get; }
ICredentialsByHost Credentials { get; set; }
SmtpDeliveryMethod DeliveryMethod { get; set; }
bool EnableSsl { get; set; }
string Host { get; set; }
string PickupDirectoryLocation { get; set; }
int Port { get; set; }
ServicePoint ServicePoint { get; }
int Timeout { get; set; }
bool UseDefaultCredentials { get; set; }
// Methods
void Send(MailMessage message);
void Send(string from, string recipients, string subject, string body);
[HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
void SendAsync(MailMessage message, object userToken);
[HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
void SendAsync(string from, string recipients, string subject, string body, object userToken);
void 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
{
public class SmtpClientProxy : ISmtpClient
{
private readonly SmtpClient smtpClient;
public SmtpClientProxy()
{
smtpClient = new SmtpClient();
smtpClient.SendCompleted += smtpClient_SendCompleted;
}
#region ISmtpClient Members
public event SendCompletedEventHandler SendCompleted;
public X509CertificateCollection ClientCertificates
{
get { return smtpClient.ClientCertificates; }
}
public ICredentialsByHost Credentials
{
get { return smtpClient.Credentials; }
set { smtpClient.Credentials = value; }
}
Finally my MailService class with the dependency injection of ISmtpClient interface and a default constructor using my SmtpClientProxy :
namespace TechHeadBrothers.Portal.Services.Mail
{
/// <summary>
/// Service to deliver Emails
/// </summary>
public class MailService : IMailService
{
private readonly ISmtpClient smtpClient;
public MailService() : this(new SmtpClientProxy())
{
}
public MailService(ISmtpClient smtpClient)
{
this.smtpClient = smtpClient;
}
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:
public interface ISmtpClient
{
// Events
event SendCompletedEventHandler 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.
private void smtpClient_SendCompleted(object sender, AsyncCompletedEventArgs e)
{
if (SendCompleted != null)
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.
/// <summary>
/// Sends a MailMessage object using the SMTP settings.
/// </summary>
/// <param name="mailMessage">Email message to be sent</param>
public void SendMailMessage(MailMessage mailMessage)
{
try
{
mailMessage.IsBodyHtml = true;
mailMessage.BodyEncoding = Encoding.UTF8;
this.message = mailMessage;
smtpClient.SendCompleted += smtpClient_SendCompleted;
smtpClient.SendAsync(mailMessage, null);
}
catch (SmtpException)
{
this.OnEmailFailed(mailMessage);
}
}
private void smtpClient_SendCompleted(object sender, AsyncCompletedEventArgs e)
{
this.OnEmailSent(message);
}
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
{
[TestFixture]
public class MailServiceTest
{
#region Setup/Teardown
[SetUp]
public void SetUp()
{
mocks = new MockRepository();
}
#endregion
private MockRepository mocks;
[Test]
public void SendMailMessageRaiseEmailSentEvent()
{
bool emailSentRaised = false;
var message = new MailMessage("lk@test.com", "mk@test.com");
var smtpClient = mocks.Stub<ISmtpClient>();
var mailService = new MailService(smtpClient);
mailService.EmailSent += ((sender, e) => { emailSentRaised = true; });
using (mocks.Record())
{
var raiser = Expect.Call(() => smtpClient.SendCompleted += null)
.IgnoreArguments().GetEventRaiser();
Expect.Call(() => smtpClient.SendAsync(message, null))
.Do((Action<MailMessage, object>) ((arg1, arg2) => raiser.Raise(message, null)));
}
using (mocks.Playback())
{
mailService.SendMailMessage(message);
Assert.That(emailSentRaised, Is.EqualTo(true));
}
}
}
}
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 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 Haack "Using Rhino Mocks To Unit Test Events on Interfaces" and another link to a post from Jean-Paul S. Boodhoo "Raising events (from a mock) using Rhino Mocks". To great post to read!