Showing posts with label tdd. Show all posts
Showing posts with label tdd. Show all posts

Thursday, September 13, 2007

Tip#3: Extend your mocking framework

Currently I am using NMock2 in my C# development. I have however made a few extensions to allow me to test some edge cases. Due to the clean design of NMock extending it is really easy.

IAction


A normal use of NMock looks like this:

Expect.Once.On(someObject).Method("methodName").WithAnyArguments().Will(Return.Value("value"));


In this statement the 'Return.Value' method returns an object that implements the IAction interface. The job of this object is to perform some action at the point the expectation matches. In this example the effect is to set the return value of the method to a known string.

However... any class implementing the IAction interface can be passed to the 'Will' method, so if you have some special need to execute code at the point the method is matched, then here is a great place to put it.

Here is an example...
[Test]
public void Move_Sleeps_UntilUpdatedWithTrue
{
Expect.Once.On(sleeper).Method("Sleep").Will(Execute.Delegate(delegate { mono.Update(false); }));
Expect.Once.On(sleeper).Method("Sleep").Will(Execute.Delegate(delegate { mono.Update(false); }));
Expect.Once.On(sleeper).Method("Sleep").Will(Execute.Delegate(delegate { mono.Update(true); }));
mono.Move(120);
}


Here I have used an IAction class that invokes a delegate at the point your expectation is met. In this case I am using it to test a piece of code that repeatedly sleeps (using a sleeper service) until the object is updated with true. I am intercepting the call to sleep and instead taking the opportunity to update the object.

Here is the code that makes that possible.
public class Execute : IAction
{
public delegate void DelegateAction();
private readonly DelegateAction action;

public static IAction Delegate(DelegateAction action)
{return new Execute(action);}

private Execute(DelegateAction action)
{this.action = action;}

public void Invoke(Invocation invocation)
{action();}

public void DescribeTo(TextWriter writer)
{}
}
So in way of explanation: the invoke method is want gets called when the expectation is met. It just invokes the delegate the 'Execute' object was constructed with. The rest is just static methods to allow you to say Execute.Delegate(...) rather than new Execute(...)

Next post I'll explain how I test firing events using another extension to NMock.

Friday, July 06, 2007

Tip:#1 Testing Events in C#

If you have a class that causes a .Net event to fire. When writing a test for the event, you can add a handler to the event that sets a flag that you then assert on in your code. Using normal delegates means the variable would need to be a class member and get initialized in Setup. Use of anonymous delegates cleans this up nicely.

[Test]
public void TriggerEvent_CausesEventThatFiresToFire()
{
Customer customer = new Customer("Ben");
string changedPropertyName = null;

customer.PropertyChanged += delegate(object sender, PropertyChangedEventArgs args)
{changedPropertyName = args.PropertyName;};

customer.Name = "Kate";

Assert.AreEqual("Kate",changedPropertyName);
}

GitHub Projects