Rash thoughts about .NET, C#, F# and Dynamics NAV.


"Every solution will only lead to new problems."

Wednesday, 25. February 2009


Mocking objects with NaturalSpec

Filed under: F#,NaturalSpec — Steffen Forkmann at 16:56 Uhr

In my last articles I gave an introduction in NaturalSpec, showed how to get started and demonstrated how we can use NaturalSpec to write automatically testable scenarios for C# projects. This time I will use the same “Car-Dealer”-sample to show how we can mock objects in NaturalSpec.

Mocking objects is an important technique in Test-driven development (TDD) and allows us to simulate complex behavior.

“If an object has any of the following characteristics, it may be useful to use a mock object in its place:

  • supplies non-deterministic results (e.g. the current time or the current temperature);
  • has states that are difficult to create or reproduce (e.g. a network error);
  • is slow (e.g. a complete database, which would have to be initialized before the test);
  • does not yet exist or may change behavior;
  • would have to include information and methods exclusively for testing purposes (and not for its actual task).”

Wikipedia

In our sample we want to mock the Dealer.SellCar() functionality. The first step is to create an C#-Interface for the Dealer:

namespace CarSellingLib
{
    public interface IDealer
    {
        Car SellCar(int amount);
    }
}

NaturalSpec is using Rhino.Mocks as the underlying mocking framework, so we have to create a reference to Rhino.Mocks.dll in our spec library.

Now we can modify our spec to:

// 1. open module
module CarSpec
// 2. open NaturalSpec-Namespace
open NaturalSpec

// 3. open project namespace
open CarSellingLib

// define reusable values
let DreamCar = new Car(CarType.BMW, 200)
let LameCar = new Car(CarType.Fiat, 45)

// 4. define a mock object and give it a name
let Bert = mock<IDealer> "Bert"

// 5. create a method in BDD-style
let selling_a_car_for amount (dealer:IDealer) =
  printMethod amount
  dealer.SellCar amount

// 6. create a scenario
[<Scenario>]
let When_selling_a_car_for_30000_it_should_equal_the_DreamCar_mocked() =
  As Bert
    |> Mock Bert.SellCar 30000 DreamCar  // 7. register mocked call
    |> When selling_a_car_for 30000
    |> It should equal DreamCar
    |> It shouldn't equal LameCar
    |> Verify

As you can see we changed part 4 (in order to get a mocked IDealer instead of the concrete Dealer). In part 7 we register our mocked behavior. We want that whenever Bert.SellCar is called with parameter 30000 the DreamCar should be returned.

The Verify-function checks if the mocked function has been called. If not the scenario will fail.

If we verify our spec with a NUnit runner we get the following output:

Scenario: When selling a car for 30000 it should equal the DreamCar mocked

- As Bert

- With Mocking

- When selling a car for 30000

=> It should equal BMW (200 HP)

=> It should not equal Fiat (45 HP)

==> OK

Tags: , , ,

1 Comment »

  1. Is there support in this framework for mocking of an object for which there is no interface, such as the standard SqlConnection in namespace System.Data.SqlClient?

    Comment by Bjarte — Friday, 17. April 2009 um 14:26 Uhr

RSS feed for comments on this post. | TrackBack URI

Leave a comment

XHTML ( You can use these tags): <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> .