Insights and outlooks on software development

S'true

How to use Rhino Mocks to expect event raises

Thursday, February 21, 2008 by Thomas L

Let's say that you have a repository that raises events whenever an entity is saved, and that you'd like to test that functionality. This is actually quite simple when using Rhino Mocks. Try to follow me here:

Create a generic IEventHandler interface, so that it can listen to all events:

 

public interface IEventHandler<T> { void OnEventRaised(object sender, T eventargs); }

Then we look at the test method:

[Test] public void RepositoryShouldRaiseEventUponSaving() { //mocks (probably best to create in the [SetUp] MockRepository _mocks = new MockRepository(); IEventHandler<EventArgs> eventHandler = _mocks.CreateMock<IEventHandler<EventArgs>>(); IOrder order = _mocks.Stub<IOrder>(); //system-under-test (ditto) OrderRepository repository = new OrderApplication.OrderRepository(); //listen to the event repository.OrderSaved += new EventHandler<EventArgs>(eventHandler.OnEventRaised); using (_mocks.Record()) { // Create an expectation on our mock's OnEventRaised method eventHandler.OnEventRaised(repository, EventArgs.Empty); } using (_mocks.Playback()) { repository.Save(order); } }

So basically, what we've done here is to create a mock of the IEventHandler interface, and we then created an expectation saying that that mock's OnEventRaised method should be called. It's as simple as that.

It's quite easy, actually, to do this for events with other arguments than EventArgs; just create a mock instance with another type argument.

Technorati tags: ,,,

Filed under having 0 kommentarer  

Test smells

by Thomas L

1. Having to explicitly set

ServiceLocator.TheService = MyMock

in the setup and doing

ServiceLocator.ClearService

in teardown points to the fact the my tested code hasn't yet matured into having its own context (preferrably set via Dependency Injection)

2. When a repository holds state, something is really wrong (and it really hurts to refactor out that(ouch))

3. Don't use easy getters in your domain model objects that hide your repository gets, i.e. using

domainModelInstance.AnotherDomainModel

when that call does

return theOtherDomainRepository.findOtherInstanceById(this.otherId)

Filed under having 0 kommentarer  

It's the small things

Monday, February 11, 2008 by Thomas L

instead of doing

Assert.AreEqual(3, myList.Count) // Do stuff that shouldn't change count Assert.AreEqual(3, myList.Count)

do this:

int count = myList.Count // Do stuff that shouldn't change count Assert.AreEqual(count, myList.Count)

Filed under having 0 kommentarer  

Having NUnit executing the same tests on two ways to create objects

by Thomas L

Let's say that you have two different ways of creating an object, let it be e.g. deserializing the instance from an xml blob and creating it manually, and you'd like to make sure that the instance has the same state and behaviour either way it's created. How to solve that? Since NUnit reads the tests to execute via reflection, we have to in some way make sure that the instances are created individually and the same test code (not a copy-pasted test fixture, that is) is run. For this problem I give the following suggestion

public class DualOrderCreationBase { [Test] public void ShouldBeInCreatedStateBeforeSave() { /* test code here */ } // More test methods here. // Note that all tests are run by NUnit both after // creation using default ctor and xmlblob. } [TestFixture] public class HavingOrderCreatedViaDefaultConstructor : DualOrderCreationBase { [SetUp] public void SetUp() { /*create order using default ctor*/} } [TestFixture] public class HavingOrderCreatedViaXmlBlob : DualOrderCreationBase { [SetUp] public void SetUp() { /*create order using xmlblob*/} }

Note here, that the two classes below inherit from the DualOrderCreationBase, which in fact contains all of the actual test methods. When NUnit reads the DualOrderCreationBase, it's not marked with the TestFixture attribute, which makes NUnit skip it. But the two classes that inherit from the DualOrderCreationBase will inherit all of the test methods together with the Test attribute, which means that we are executing the same tests for objects instantiated in two different ways, just as we wanted!

Regarding project organization, it seems as if having all of the three classes in their own file is quite nice. This organization more or less means that the file encapsulates a specific behaviour of the domain object.

Technorati tags: ,,

Filed under having 0 kommentarer