Insights and outlooks on software development

S'true

LINQ to AD

Sunday, December 16, 2007 by Thomas L

So someone has finally done what I've been thinking about doing for a great deal of time now, implementing a way to use LINQ for querying the Active Directory via the System.DirectoryServices API in .NET. Sweet!

(If I only could get the subversion checkout to work with CodePlex...)

Filed under having 0 kommentarer  

Rhino Mocks introduction

Sunday, December 9, 2007 by Thomas L

Since the documentation is a bit rudimentary over at ayende's site, I've decided to try to cover some of the broad range of functionality of the kick-ass mocking framework that is Rhino Mocks.

If you don't know what a mock is and which types of test doubles that there are, read this article by Fowler first.

This article will introduce us to Rhino Mocks somewhat, later I have plans to elaborate on more advanced topics like constraints etc. But let's dig into the code now. Let's say that we're building some kind of order application, where the user enters an order and adds a number of order lines to that order, and then saves. What I'd like to test now, is that the user can't add an order line to the order where the order line has no product (i.e. it's null). The base for this test is basically this:

namespace OrderApplication { public interface IOrderLine { float? Amount { get; set; } IProduct Product { get; set; } } }

namespace OrderApplication { public class Order { public Order() { _orderLines = new List<IOrderLine>(); } private List<IOrderLine> _orderLines; public void AddOrderLine(IOrderLine orderLine) { _orderLines.Add(orderLine); } public IList<IOrderLine> OrderLines { get { return _orderLines; } } } }

In the code above, all that's done is that the AddOrderLine method will take an IOrderLine. What I'd like to do is to check, when adding the OrderLine to the Order, is that the Product property on the IOrderLine isn't null.

The first thing to check for is that the AddOrderLine method should check the Product property on the order line added. This will be accomplished by doing something like this:

using NUnit.Framework; using Rhino.Mocks; namespace OrderApplication.Tests { [TestFixture] public class OrderBehaviour { private MockRepository _mocks; [SetUp] public void SetUp() { _mocks = new MockRepository(); } [Test] public void ShouldCheckForProductWhenAddingOrderLine() { //the orderline to add IOrderLine orderLine = _mocks.CreateMock<IOrderLine>(); //the order to test Order order = new Order(); using (_mocks.Record()) { Expect.Call(orderLine.Product).Return(_mocks.Stub<IProduct>()); } using (_mocks.Playback()) { order.AddOrderLine(orderLine); } } } }

In the code above I add an expectation that the AddOrderLine method should call orderLine.Product, and I make it return just something, by having Rhino Mocks creating a stub for me. When running the test, I get a failure; since we added the expectation that the Order instance should get the Product of the OrderLine, and it's not done (look at the Order code above), the NUnit test fails. In order to make this work, we'll add some code:

public void AddOrderLine(IOrderLine orderLine) { if (orderLine.Product == null) return; _orderLines.Add(orderLine); }

I only added a null check, and now the test passes (since the Order class gets the Product property). But perhaps we'd like the application not to fail silently, but instead throw an exception? All right, in the spirit of TDD, we'll add a test for this:

[Test, ExpectedException(typeof(ArgumentException))] public void AddingOrderLineWithoutProductWillFail() { //the orderline to add IOrderLine orderLine = _mocks.CreateMock<IOrderLine>(); //the order to test Order order = new Order(); using (_mocks.Record()) { Expect.Call(orderLine.Product).Return(null); } using (_mocks.Playback()) { order.AddOrderLine(orderLine); } }

Now, I've added the attribute ExpectedException to fail the test if the called code doesn't throw an exception. Notice that the expectation line now says .Return(null), which basically will make Rhino.Mocks return null when the Product property is looked up. Running this test directly will of course fail, since we don't throw the ArgumentException in the AddOrderLine method. After adding it, the method will look like this:

public void AddOrderLine(IOrderLine orderLine) { if (orderLine.Product == null) throw new ArgumentException("Product is null!"); _orderLines.Add(orderLine); }

So wrapping up, I've shown you how to write test code in which we add method call expectations. There are more to show, though, Rhino Mocks have a really nice Constraints feature, where we can add constraints for specific parameters in a method call. Hopefully I'll get to that in time.

Technorati tags: ,,,

Filed under having 0 kommentarer  

Using TestDriven.NET efficiently

by Thomas L

TestDriven.NET is an exceptionally good tool when you're working in a test driven fashion (you're doing that, aren't you?), but it's quite cumbersome having to reach for the mouse and rightclick in the editor whenever I want to run or rerun a test. Fortunately, it's possible to hook the TestDriven.NET RunTests action in Tools->Options inside Visual Studio. Do like this:

Under Tools->Options, Go to the Environemnt->Keyboard option. In the "Show commands containing", write TestDriven and then navigate to the RunTests command.

image

Then press the shortcut you wish to map to the command; in the screenshot above I've mapped it to Ctrl-F7, which I find works well, especially as the Start Without Debugger is mapped to Ctrl-F5. Then press Assign to map the keys to the command.

Now, the RunTests will function just as when you right-click and select Run Tests, i.e. the context in which the cursor sits is the basis for the tests to run. If the cursor is on the class level, all tests in the TestFixture are run, and if it's on method level, the specific Test is run. Quite nice, I find.

Do the same (with another key mapping, of course :) with TestDriven.NET.RerunTests and TestDriven.NET.Debugger. I've mapped them to Ctrl-Shift-F7 and LeftAlt-F7 respectively (for some reason, my VMware Fusion refuses to send the Ctrl-LeftAlt-F7, which I use at work, to my virtual Windows machine).

Using RerunTests I'm getting a quite nice Red-Green kind of workflow, writing a test, executing it and then I flip over to the class under test to fix, rerun, fix, rerun etc.

I hope you find TestDriven.NET as useful as I do. Right now, I can't live without it.

Filed under having 0 kommentarer