REST lesson learned: Avoid user supplied data in URI segments

Monday, 29 April 2013 12:07:00 UTC

Be careful with user-supplied data in URI segments.

This is a lesson about design of REST APIs that I learned the hard way: if you built service URIs from dynamic data, be careful with the data you allow in URI segments.

Some HTTP frameworks (e.g. the ASP.NET Web API) let you define URI templates or routes that handle incoming requests - e.g.

routeTemplate: "api/{controller}/{id}"

which means that a request to http://foo.ploeh.dk/api/fnaah/sgryt would map the value "fnaah" to controller, and the value "sgryt" to id.

If you are building a level 2 or less service, you may even publish your URI templates to consumers. If you are building a level 3 RESTful API, you may not be publishing your URI templates, but you can still use them internally.

Avoid user-supplied data in URI segments.

Be careful with the source of data you allow to populate URI segments of your URI template. At one point, I was involved with designing a REST API that (among other things) included a 'tag cloud' feature. If you wanted to see the contents of a specific tag, you could navigate to it.

Tags were all user-defined strings, and they had no internal ID, so our first attempt was to simply treat the value of the tag as the ID. That seemed reasonable, because we wanted the tag resource to list all the resources with that particular tag value. Thus, we modeled the URI template for tag resources like the above route template.

That worked well for a URL like http://foo.ploeh.dk/api/tags/rock because it would simply match the value "rock" to the id variable, and we could then list all resources tagged with "rock".

However, some user had defined a tag with the value of "sticky & sweet" (notice the ampersand character), which meant that when you wanted to see all resources with this link, you would have to navigate to http://foo.ploeh.dk/api/tags/sticky & sweet. However, that sort of URL is considered dangerous, and IIS will (by default) refuse to handle it.

Can you get around this by URL encoding the value? No, it's part of the request path, not part of any query string, so that's not going to work. The issue isn't that the URL is invalid, but that the server considers it to be dangerous. Even if you URL encode it, the server will decode it before handling it, and that would you leave you at square one.

You can either change the URI template so that the URL instead becomes http://foo.ploeh.dk/api/tags?id=sticky%20%26%20sweet. This URL encodes the query string (the part of the URL that comes after the ?), but gives you an ugly URL.

Another alternative is to be very strict about input validation, and only allow users to create values that are safe when used as URI segments. However, that's putting an unreasonable technical limitation on an application feature. If a user wants to tag a resource with "sticky & sweet", the service should allow it.

In the end, we used a third alternative: we assigned an internal ID to all tags and mapped back and forth so that the URL for the "sticky & sweet" tag became http://foo.ploeh.dk/api/tags/1234. Yes: that makes it impossible to guess the URL, but we were building a level 3 RESTful API, so clients are expected to follow links - not guess the URL.


REST lessons learned

Monday, 29 April 2013 00:00:00 UTC

This post provides an overview of some lessons I learned while bulding non-trivial REST APIs.

Last year I spent a good deal of the year designing and implementing a handful of non-trivial REST APIs for a customer of mine. During that process, I learned some small lessons about the design of RESTful systems that I haven't seen described elsewhere, and I want to share these lessons with you.

In order to learn the concepts and philosphy behind REST, I think that REST in Practice is a great resource (pun intended), but when it comes to practical guidance, I find the RESTful Web Services Cookbook invaluable. It's full of useful and concrete tips and tricks for building RESTful APIs, but I don't remember reading about the following lessons, that I had to learn the hard way.

There's so much hype and misrepresentation about REST that I have to point out that when I'm talking about REST, I mean full-on, level 3 REST, with resources, verbs, hypermedia controls and the works.

Each of these lessons deserves a small article of its own, but here's an overview:

I hope you find these tips useful.


How to change the Generate Property Stub refactoring code snippet in Visual Studio 2012

Tuesday, 23 April 2013 14:00:00 UTC

This post describes how to change the code template for the "Generate Property Stub" refactoring in Visual Studio 2012.

This is mostly a quick note for my own benefit (since I just spent half an hour chasing this down), but I'm posting it here on the blog, in case someone else might find it useful. Here's how to change the code snippet for the "Generate Property Stub" smart tag in Visual Studio 2012:

The template for this code is defined in

C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC#\Snippets\1033
\Refactoring\GenerateProperty - Auto Property.snippet

You can open this file and hand-edit it, but contrary to previous versions of Visual Studio, it seems that you have to restart Visual Studio before the change takes effect.

If you do this, be sure that you know what you're doing; you'd be mucking around with the internals of your Visual Studio installation.


Advanced Unit Testing Pluralsight course

Monday, 15 April 2013 18:29:00 UTC

Service announcement: my new Pluralsight course Advanced Unit Testing is now available. Read more in Pluralsight's announcement, or go straight to the course.

If you don't already have a Pluralsight account, you can get a free trial of up to 200 minutes.


FizzBuzz kata in Clojure

Thursday, 11 April 2013 06:20:00 UTC

This post describes my first experience with doing the FizzBuzz kata in Clojure.

After having looked at Clojure for some time, I finally had a bit of time to play with it, so I decided to do the FizzBuzz kata in Clojure.

Single fizzbuzz function

Clojure has a built-in testing framework, so I wrote a Parameterized Test for a single fizzbuzz function. Using TDD, I added test cases a little at a time, attempting to follow the Transformation Priority Premise, but the end result is this:

(ns fizzbuzz.core-test
  (:use clojure.test
        fizzbuzz.core))

(deftest fizzbuzz-test
  (are [expected i] (= expected (fizzbuzz i))
       "1" 1
       "2" 2
       "Fizz" 3
       "4" 4
       "Buzz" 5
       "Fizz" 6
       "7" 7
       "8" 8
       "Fizz" 9
       "Buzz" 10
       "11" 11
       "Fizz" 12
       "13" 13
       "14" 14
       "FizzBuzz" 15
       "FizzBuzz" 30))

Clojure syntax is somewhat backwards from what I'm normally used to, but the are macro expands into a collection of tests that each evaluate whether the result of invoking the fizzbuzz function with i is equal to expected.

Through a series of transformations of the SUT, I ended up with this implementation of the fizzbuzz function:

(ns fizzbuzz.core)

(defn fizzbuzz [i]
  (cond
    (= 0 (mod i 15)) "FizzBuzz"
    (= 0 (mod i 3)) "Fizz"
    (= 0 (mod i 5)) "Buzz"
    :else (str i)))

This defines a function called fizzbuzz taking a single argument i. The cond macro evaluates each test and returns the expression associated with the first test that evauluates to true. The first test checks if i is divisible with 15 and returns "FizzBuzz" if this is the case; the next test checks if i is divisible with 3 and returns "Fizz" if this is true, and so on.

Printing a range of fizzbuzz values

The task defined by the kata is to print all FizzBuzz values from 1 to 100, so the above function is't the final solution. The next step I took was to write a test that defines a version of the fizzbuzz function taking two parameters:

(def acceptance-expected
"1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
Fizz
22
23
Fizz
Buzz
26
Fizz
28
29
FizzBuzz
31
32
Fizz
34
Buzz
Fizz
37
38
Fizz
Buzz
41
Fizz
43
44
FizzBuzz
46
47
Fizz
49
Buzz
Fizz
52
53
Fizz
Buzz
56
Fizz
58
59
FizzBuzz
61
62
Fizz
64
Buzz
Fizz
67
68
Fizz
Buzz
71
Fizz
73
74
FizzBuzz
76
77
Fizz
79
Buzz
Fizz
82
83
Fizz
Buzz
86
Fizz
88
89
FizzBuzz
91
92
Fizz
94
Buzz
Fizz
97
98
Fizz
Buzz")

(deftest acceptance-test
  (is (= acceptance-expected (fizzbuzz 1 101))))

I decided to define the acceptance-expected value outside of the test case itself, as I thought that made the test a bit more readable. The test case is defined by the is macro and states that the expected value is acceptance-expected and the actual value is the result of invoking the fizzbuzz function with two arguments: 1 as the (inclusive) start value, and 101 as the (exclusive) end value. The above code listing of fizzbuzz only accept one argument, but the new test case requires two arguments, so I added an overload to the function:

(defn fizzbuzz
  ([i]
    (cond
      (= 0 (mod i 15)) "FizzBuzz"
      (= 0 (mod i 3)) "Fizz"
      (= 0 (mod i 5)) "Buzz"
      :else (str i)))
  ([start end]
    (apply str
      (interpose "\n"
        (map fizzbuzz (range start end))))))

The previous implementation is still there, now contained within the overload taking a single argument i, but now there's also a new overload taking two arguments: start and end.

This overload generates a sequence of integers from start to end using the range function. It then maps that sequence of integers into a sequence of strings by mapping each integer to a string with the fizzbuzz function. That gives you a sequence of strings such as ("1" "2" "Fizz" "4" "Buzz").

In order to print all the FizzBuzz strings, I need to interpose a newline character between each string, which produces a new sequence of strings such as ("1" "\n" "2" "\n" "Fizz" "\n" "4" "\n" "Buzz"). To concatenate all these strings, I apply the str function to the sequence.

Printing FizzBuzz values from 1 to 100

The requirements of the kata is to print all FizzBuzz values from 1 to 100, and the code already does this. However, I interpret the kata as requiring a single function that takes no parameters, so I added an acceptance test case:

(deftest acceptance-test
  (is (= acceptance-expected (fizzbuzz 1 101)))
  (is (= acceptance-expected (fizzbuzz))))

Notice the second test case in the last line of code that invokes the fizzbuzz function without any parameters. It's easily resolved by adding a third overload:

(defn fizzbuzz
  ([]
    (fizzbuzz 1 101))
  ([i]
    (cond
      (= 0 (mod i 15)) "FizzBuzz"
      (= 0 (mod i 3)) "Fizz"
      (= 0 (mod i 5)) "Buzz"
      :else (str i)))
  ([start end]
    (apply str
      (interpose "\n"
        (map fizzbuzz (range start end))))))

As you can see, the first overload takes no parameters and simply invokes the previously desribed overload with the start and end arguments.

FWIW, this entire solution is structurally similar to my implementation of FizzBuzz in F#.


Ploeh blog syndication feed addresses

Tuesday, 09 April 2013 07:53:00 UTC

Service announcement about syndication feed addresses for ploeh blog.

Now that Google Reader is closing down and a lot of my readers may want to migrate their ploeh blog subscription to another service, I think it's the right time for a quick post about ploeh blog's syndication feed addresses.

When I migrated my blog to Jekyll I made it a priority to ensure a certain level of backwards compatibility. The permalinks for the old posts are still served, although they are now redirects. For that reason, I also left the old syndication feed addresses in place. Specifically, I left this old RSS feed address in place: http://blog.ploeh.dk/SyndicationService.asmx/GetRss. This feed address sort of works, but has issues.

There are several problems with the 'legacy' feed address:

  • Due to the way Jekyll works, the address actually points to an index.html file. Since a Jekyll-powered site is a static site, I don't control the server, and thus I can't manipulate the HTTP headers for individual resources. HTML files are served with the "text/html" Content-Type, which doesn't fit the XML content. Some clients seem to dislike this.
  • Google Reader has created some 'ghost' entries based on the feed. I wonder if it has anything to do with the faulty Content-Type.
  • Other users have reported that their clients (e.g. Outlook) don't like the feed. Again, I suspect it's because of the faulty Content-Type. While I think those clients should follow Postel's law, they apparently don't.
  • The address looks very implementation-specific.

However, ploeh blog has new, 'proper' syndication feed addresses, so if you're already in the process of migrating your subscriptions away from Google Reader, please take a moment to update your subscription. That 'legacy' RSS address may not stick around forever.

The proper syndication feed addresses for ploeh blog are:

Both serve responses with the "text/xml" Content-Type.


How to automatically populate properties with AutoMoq

Monday, 08 April 2013 05:55:00 UTC

This post explains how to automatically populate properties when using AutoFixture.AutoMoq.

In a previous blog post I described how to configure AutoFixture.AutoMoq to set up all mock instances to have 'normal' property behavior. This enables you to assign and retrieve values from properties defined by interfaces, but still doesn't fill those properties with values.

Apparently, people want to do that, so here's how to do it with the AutoMoq glue library.

This solution builds upon the PropertiesPostprocessor described in my previous blog post. All you have to do is define a different Customization for AutoFixture so that, instead of using the AutoMoqPropertiesCustomization described in the previous post, you'll need a variation:

public class AutoPopulatedMoqPropertiesCustomization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Customizations.Add(
            new PropertiesPostprocessor(
                new MockPostprocessor(
                    new MethodInvoker(
                        new MockConstructorQuery()))));
        fixture.ResidueCollectors.Add(
            new Postprocessor(
                new MockRelay(),
                new AutoPropertiesCommand(
                    new PropertiesOnlySpecification())));
    }
 
    private class PropertiesOnlySpecification : IRequestSpecification
    {
        public bool IsSatisfiedBy(object request)
        {
            return request is PropertyInfo;
        }
    }
}

The PropertiesPostprocessor assigned to the Fixture's Customizations has the same configuration as shown in AutoMoqPropertiesCustomization, but the object graph passed to the Fixture's ResidueCollectors is different. It's still a MockRelay, but now decorated with a Postprocessor instance, configured with an AutoPropertiesCommand instance, which is the class in AutoFixture responsible for implementing the AutoProperties feature.

The only thing special about this configuration is that you need to pass a PropertiesOnlySpecification to the AutoPropertiesCommand instance. This is because, by default, AutoPropertiesCommand attempts to fill both properties and fields of a generated instance (we call that a specimen), but it turns out that when you ask Moq to generate an instance of an interface, the generated type has a lot of public fields that you don't want to mess with. The PropertiesOnlySpecification class filters the population algorithm so that it only attempts to populate public properties.

This test passes:

[Fact]
public void AutoPopulatedProperties()
{
    var fixture = new Fixture().Customize(
        new AutoPopulatedMoqPropertiesCustomization());
    var h = fixture.Create<IHasProperties>();
 
    Assert.NotEqual(default(string), h.Text);
    Assert.NotEqual(default(int), h.Number);
}

With the described AutoPopulatedMoqPropertiesCustomization, AutoFixture will populate all writable properties on interfaces generated by Moq. I still don't think this is a good idea, which is why it isn't the default behavior for AutoFixture, but as you can tell, it's not too hard to do.


How to configure AutoMoq to set up all properties

Friday, 05 April 2013 15:13:00 UTC

This post explains how to configure AutoFixture.AutoMoq to setup all interface properties to behave like normal properties.

From time to time, people want the AutoFixture.AutoMoq Auto-Mocking Container to set up all mock instances to have 'normal' property behavior.

By default, Moq doesn't implement any members of an interface. You have to explicitly configure the desired behavior using the Setup methods. This is also true for properties (which are really only special methods).

Consider, as an example, this interface:

public interface IHasProperties
{
    string Text { get; set; }
 
    int Number { get; set; }
}

Personally, I think such an interface design is a design smell, but that's not the issue here.

Moq behavior

The issue is that by default, Moq behaves like this:

[Fact]
public void DefaultMoqDoesNotSetupProperties()
{
    var h = new Mock<IHasProperties>().Object;
 
    h.Text = "foo";
    h.Number = 42;
 
    Assert.Equal(default(string), h.Text);
    Assert.Equal(default(int), h.Number);
}

As you can infer from this test, the IHasProperties instance completely ignores any attempt at assigning values to the properties. When you attempt to read the property values, Moq returns the default value for the property type - often null.

You can configure each property individually, but you can also configure the Mock instance to implement all properties as thought they are normal, well-behaved properties:

[Fact]
public void ManualSetupProperties()
{
    var td = new Mock<IHasProperties>();
    td.SetupAllProperties();
    var h = td.Object;
 
    h.Text = "foo";
    h.Number = 42;
 
    Assert.Equal("foo", h.Text);
    Assert.Equal(42, h.Number);
}

Notice the use of the SetupAllProperties method. So far, this is all about Moq, and really has nothing to do with AutoFixture.

AutoFixture.AutoMoq and interface property behavior

Adhering to the Principle of least surprise, the AutoFixture.AutoMoq glue library doesn't change this behavior:

[Fact]
public void DefaultAutoMoqDoesNotSetupProperties()
{
    var fixture = new Fixture().Customize(new AutoMoqCustomization());
    var h = fixture.Create<IHasProperties>();
 
    h.Text = "foo";
    h.Number = 42;
 
    Assert.Equal(default(string), h.Text);
    Assert.Equal(default(int), h.Number);
}

However, it's easy to change the behavior in an ad hoc manner:

[Fact]
public void ManualSetupPropertiesOnAutoMoq()
{
    var fixture = new Fixture().Customize(new AutoMoqCustomization());
    var h = fixture.Create<IHasProperties>();
    Mock.Get(h).SetupAllProperties();
 
    h.Text = "foo";
    h.Number = 42;
 
    Assert.Equal("foo", h.Text);
    Assert.Equal(42, h.Number);
}

As you can see, you can use the static Mock.Get method to get the underlying Mock<IHasProperties> and explicitly invoke the SetupAllProperties method.

If you prefer AutoFixture to automate this for you, it's fairly easy to do. First, you'll need to write an ISpecimenBuilder that hooks into the Mock creation process and invokes the SetupAllProperties method:

public class PropertiesPostprocessor : ISpecimenBuilder
{
    private readonly ISpecimenBuilder builder;
 
    public PropertiesPostprocessor(ISpecimenBuilder builder)
    {
        this.builder = builder;
    }
 
    public object Create(object request, ISpecimenContext context)
    {
        dynamic s = this.builder.Create(request, context);
        if (s is NoSpecimen)
            return s;
 
        s.SetupAllProperties();
        return s;
    }
}

This class must decorate another ISpecimenBuilder, whose responsibility it is to create Mock<T> instances. The example code shown here is only a proof of concept, so it only does the bare minimum of defensive coding, assuming that if the object returned from the decorated ISpecimenBuilder is not a NoSpecimen, then it must be a Mock instance. In that case, it invokes SetupAllProperties on it.

You'll need to compose this PropertiesPostprocessor class together with all the other building blocks of the AutoMoq glue library. Currently, there's no specific hook into AutoMoqCustomization that enables you to do that, but if you decompose AutoMoqCustomization, you'll realize how easy it is to replicate the behavior while adding your new PropertiesPostprocessor class:

public class AutoMoqPropertiesCustomization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Customizations.Add(
            new PropertiesPostprocessor(
                new MockPostprocessor(
                    new MethodInvoker(
                        new MockConstructorQuery()))));
        fixture.ResidueCollectors.Add(new MockRelay());
    }
}

The only difference from the AutoMoqCustomization implementation is the addition of PropertiesPostprocessor decorating MockPostprocessor.

This test now passes:

[Fact]
public void AutoSetupProperties()
{
    var fixture = new Fixture().Customize(
        new AutoMoqPropertiesCustomization());
    var h = fixture.Create<IHasProperties>();
 
    h.Text = "foo";
    h.Number = 42;
 
    Assert.Equal("foo", h.Text);
    Assert.Equal(42, h.Number);
}

As you can see, the Mock object created by AutoFixture now implements properties as normal, well-behaved properties.


Structural Inspection

Thursday, 04 April 2013 07:50:00 UTC

One way to unit test a complex system is to test the behavior of each part and then verify that the structure of the composition is correct.

How do you unit test complex systems? How do you apply TDD to a complex system? This seems to be one of the most difficult questions related to unit testing.

First, a little language lesson. Complex means that something is, by its very nature, composed of parts.

"Complexity is intrinsic. Something is complex if it involves a lot of [metaphorical] moving parts even when considered as a Platonic ideal."
You could say that complexity is the opposite of unity. It's not the same as complicated.
"Complication is extrinsic. Something is complicated by external influences, or because of external influences."
So how do you unit test complex systems?

Traditional introductions to TDD tend to focus on simple systems, such as

  • Stack
  • Fibonacci
  • Prime factors
  • Bowling game
  • Word wrap
Common for these topics is that it's easy to explain the requirements and get started demonstrating how TDD works. It's what John Sonmez calls level 1 unit testing. This is great if the purpose is to introduce the concept of TDD to programmers who are unfamiliar with the TDD process. However, the problem is that it doesn't really explain how to unit test complex systems (level 3 and up).

A partial answer is provided by one of my favorite quotes from Design Patterns:

Favor object composition over class inheritance.
If you can unit test the behavior each sub-component in isolation, then 'all' you need to do is to prove that those parts interact correctly. You can do this by a technique I call Structural Inspection. The idea is to inspect the structure of composed parts - a Facade, if you will. If you know that two composed parts interact in a certain way, and you can also prove that the composed parts have the desired identity, you can prove that a complex system works correctly.

Before I go on, I think it's important to point out that Structural Inspection is one among several approaches you can take to unit testing and TDD. Personally, I've had quite a few successes with this technique, but it tends to require a rather meticulous modus operandi, so it's not suitable in all cases. It works best against complex systems where you can't afford mistakes. The disadvantage is that you'll have to write a lot of tests and at times you may feel that you are moving very slowly, but the advantage is that the final system is not only likely to be correct, but it's proven to be correct.

A note about the following example: it describes a way to unit test a shopping basket, including discounts, VAT, totals, etc. You may think that there are easier ways, and that the technique I describe is overkill. However, I've attempted to strike a balance between something that is sufficiently complex to make the examples realistic, yet still not so complex that it can fit in a single (although long) article.

API design

Structural Inspection is not only a unit testing technique; it's also an API design philosophy:

What you compose, you can also expose.
This means that if you compose objects by applying the Dependency Inversion Principle, you can expose, as a property or field, what you just injected.

public class Discount : IBasketElement
{
    public Discount(decimal amount)
 
    public decimal Amount { get; }
 
    public IBasketVisitor Accept(IBasketVisitor visitor)
}

In the above example, the Discount class contains an amount (a decimal value), and implements the IBasketElement interface. The Accept method is the only member defined by that interface. The design philosophy of Structural Inspection is very simple: because it accepts an amount in its constructor, it should also expose that value as a public Amount property (or field).

People unused to TDD often react in one of two ways:

  • "I don't like adding members only for testing"
  • "It breaks encapsulation"

Well, if you follow TDD, all production code you write, you write as a response to a test you just wrote. The unit tests are the first client of the production API. The important part is whether or not adding a member breaks encapsulation. Adding a property that exposes something that was passed into the constructor by a client, can hardly be said to break encapsulation. Exposing properties doesn't necessarily break encapsulation. Even if you believe that encapsulation is 'information hiding', it makes no sense to hide data that was passed into the object instance by a third party. The object simply isn't the exclusive owner of that data.

However, since the object (like the Discount class in the above example) already holds an instance of the data as a field, it might as well be courteous and share that information with its client. Otherwise, that would just put the onus on the client to remember the value it passed via the constructor.

Ultimately, adding a property to a concrete class has no impact on the exposed interface. Since a constructor is an implementation detail, by corollary Inspection Properties are also implementation details. While they don't break encapsulation, they are only part of the concrete class. At the interface level, they are invisible. Interfaces are general, but concrete types are specific.

Unit testing

The API design philosophy is easy to understand, but what does that mean for unit testing? The great thing is that it's possible to test each part of the whole in isolation, and then subsequently prove that parts correctly interact.

Consider the Discount class. It's easy to prove that the injected amount is properly exposed as a property:

[Theory]
[InlineData(1)]
[InlineData(2)]
public void AmountIsCorrect(int expected)
{
    var sut = new Discount(expected);
    var actual = sut.Amount;
    Assert.Equal(expected, actual);
}

Now, that's not particularly interesting in itself, but it's a small part of a larger whole. In the big picture, the concrete class is invisible, but the interfaces it implements are important. In this example, it must implement the IBasketElement interface. That's also easy to prove:

[Fact]
public void SutIsBasketElement()
{
    var sut = new Discount();
    Assert.IsAssignableFrom<IBasketElement>(sut);
}

The above fact only states that Discount implements IBasketElement, but not that it correctly implements it. One last test verifies that this is, indeed, the case:

[Fact]
public void AcceptReturnsCorrectResponse()
{
    var expected = new Mock<IBasketVisitor>().Object;
    var sut = new Discount();
 
    var visitorStub = new Mock<IBasketVisitor>();
    visitorStub.Setup(v => v.Visit(sut)).Returns(expected);
    var actual = sut.Accept(visitorStub.Object);
 
    Assert.Same(expected, actual);
}

This test verifies that the Accept method is correctly implemented. It sets up visitorStub in such a way that it'll only return expected if sut is passed to the Visit method. The actual value returned by the Accept method must be the same as the expected value.

Given these tests, the implementation must look something like this:

public class Discount : IBasketElement
{
    private readonly decimal amount;
 
    public Discount(decimal amount)
    {
        this.amount = amount;
    }
 
    public IBasketVisitor Accept(IBasketVisitor visitor)
    {
        return visitor.Visit(this);
    }
 
    public decimal Amount 
    {
        get { return this.amount; }
    }
}

With these tests in place, you can pretty much forget about the Discount class. It has appropriate concrete behavior and correctly implements the IBasketElement protocol. You can write similar tests for all other classes that implements IBasketElement.

That may still seem trivial, but it begins to become interesting when you consider that a Basket is simply a collection of IBasketElement instances. That enables you to write this (Behavior Verification) test:

[Fact]
public void AcceptReturnsCorrectResult()
{
    // Fixture setup
    var v1 = new Mock<IBasketVisitor>().Object;
    var v2 = new Mock<IBasketVisitor>().Object;
    var v3 = new Mock<IBasketVisitor>().Object;
    var e1Stub = new Mock<IBasketElement>();
    var e2Stub = new Mock<IBasketElement>();
    e1Stub.Setup(e => e.Accept(v1)).Returns(v2);
    e2Stub.Setup(e => e.Accept(v2)).Returns(v3);
 
    var sut = new Basket(e1Stub.Object, e2Stub.Object);
    // Exercise system
    var actual = sut.Accept(v1);
    // Verify outcome
    Assert.Same(v3, actual);
    // Teardown
}

That may look difficult, but it simply states that when the Accept method is invoked with v1, it will pass v1 to the first IBasketElement, and the return value will be v2, which is then passed to the second IBasketElement, which returns v3, which is the last result and thus expected to be returned by the Basket instance itself. This works for all Mock<IBasketVisitor>.Object instances, so according to the Liskov Substitution Principle, it will work for any IBasketVisitor that conforms to the protocol.

In other words: because you know that Discount correctly implements IBasketElement, you are guaranteed that if there's a Discount element in a basket, it will call any visitor's Visit(Discount) method. This puts you in a position to implement an IBasketVisitor to calculate the total for the basket.

A BasketTotalVisitor must correctly implement all Visit methods defined by the IBasketVisitor interface and accumulate a total. However, whenever it encounters a Discount, it must subtract the discount from the total. Because BasketTotalVisitor is only a small part of a complex whole, this is easy to test:

[Theory]
[InlineData(1, 1)]
[InlineData(2, 1)]
[InlineData(3, 2)]
public void VisitDiscountReturnsCorrectResult(
    int initialTotal,
    int discount)
{
    var sut = new BasketTotalVisitor(initialTotal);
 
    var actual = sut.Visit(new Discount(discount));
 
    var btv = Assert.IsAssignableFrom<BasketTotalVisitor>(actual);
    Assert.Equal(initialTotal - discount, btv.Total);
}

Notice how this test uses Structural Inspection by verifying that the returned IBasketVisitor is, indeed, a BasketTotalVisitor instance, which has a Total property that the test verifies matches the expected value. It can only do that because the concrete BasketTotalVisitor class exposes the Total property.

Verifying the whole

You can keep on working like this: establishing that the behavior of each small part follows the correct protocols. Once all fine-grained building blocks are in place, the only thing left to do is to verify that they are correctly composed. This is where Structural Inspection is very powerful. This is how you can verify that a BasketPipeline will have the correct behavior:

[Fact]
public void SutCorrectlyConvertsToPipe()
{
    CompositePipe<Basket> sut = new BasketPipeline();
 
    var visitors = sut
        .Cast<BasketVisitorPipe>()
        .Select(bvp => bvp.Visitor);
 
    var dv = Assert.IsAssignableFrom<VolumeDiscountVisitor>(visitors.First());
    Assert.Equal(500, dv.Threshold);
    Assert.Equal(.05m, dv.Rate);
 
    var vv = Assert.IsAssignableFrom<VatVisitor>(visitors.ElementAt(1));
    Assert.Equal(.25m, vv.Rate);
 
    var btv = Assert.IsAssignableFrom<BasketTotalVisitor>(visitors.Last());
}

This may look like a verbose test, but it's actually quite information-dense.

First, the BasketPipeline is a CompositePipe<Basket>, and while I haven't shown that part in this article, I know from other unit tests that this class adheres to the Liskov Substitution Principle, so if the test can verify that its content is correct, the composed behavior must also be correct.

In this test case, you can project all the contained pipes into the visitors they adapt. This is only possible because the concrete class BasketVisitorPipe exposes the concrete Visitor property. This is Structural Inspection in action.

The BasketPipeline should be able to apply a volume discount, calculate VAT and the total. Because all the small parts have the correct behavior, you only need to verify that the BasketPipeline has the correct structure.

A business rule states that a volume discount of five percent should be applied if the total value of all basket items is 500 or more. This means that the first visitor should be a VolumeDiscountVisitor, and its threshold should be 500 and the rate .05. You can use Structural Inspection to verify that this is the case.

A legal requirement is that a VAT rate of 25 percent (real Danish VAT rate) should be applied to the value of the basket. This means that the next visitor should be a VatVisitor, and its rate should be .25 .

Finally, the total price for the basket, including discounts and VAT should be calculated. This means that the last visitor should be a BasketTotalVisitor.

The test verifies the structure of the API's Facade, and because the Facade has the correct structure and previous tests have proven that all the parts have the correct behavior, the Facade must have the desired higher-order behavior.

In order to write this article, I TDD'ed all the code presented here (and more), and I deliberately didn't try to apply the BasketPipeline to some Basket instances until I had all the structure in place. Once I had that, I wrote a few Facade Tests as sanity checks, and they all passed in the first attempt.

Conclusion

Structural Inspection is a useful technique when you need to unit test a complex system, and you need a high degree of confidence that everything works correctly. It's not the only option available to you. Another option is to use Triangulation with a large set of Facade Tests, but there may come a time where the number of test cases required to exercise all possible combinations of business rules becomes so large that Structural Inspection may be a better alternative.

The code I wrote for this article contains 136 test cases, distributed over 88 test methods. It has 100 percent code coverage, and it covers 67 members over 11 classes and 3 interfaces. That's probably too enterprisey for a simple shopping basket calculation that only does volume discounts, VAT and total calculation. However, the way I've modeled this Basket API is quite extensible, so it may be quite well-suited for complex shopping baskets that might include various sorts of inclusive and exclusive discounts, VAT rates that are dependent on the category of goods in the basket, or that may be dependent on the shipping destination. Add to that calculation of shipping rates based on shipping origin and destination, as well as various characteristics (weight, volume, etc.) of the items in the basket, and Structural Inspection starts to look attractive.

Resources

For more details:


Comments

Jin-Wook Chung

Thank you for sharing the great article. Recently I have been curious about how the structural instpection can work on funtional programming. Because funtion does not expose any properties to be inspected, I think that the only way to verify that whole thing correctly behaves is doing integration test.

I was wondering whether you had a good approach about it.

2015-02-13 02:12 UTC

Thank you for writing. With functions, I've yet to find a good alternative to Structural Inspection, so I find myself writing more Integration Tests when I write F# code. On the other hand, because the F# type system is so much stronger than e.g. C#, I've also found that I can design data structures in such a way that illegal states become unrepresentable, and that again means that I need to write fewer unit tests than I would have to with F#.

Thus, even though I may have to write slightly more Integration Tests, I'm still quite happy with the trade-off.

2015-02-14 11:07 UTC

Why trust tests?

Tuesday, 02 April 2013 07:40:00 UTC

Tests are trustworthy if they are simple and you've seen them fail.

When I started out with TDD some ten years ago, it was really hard to convince programmers that unit testing was valuable. It's better today, but much software is still produced without test coverage. One of the most common arguments for unit tests is to ask the question: "How do you know that your code works?"

That's a darn good question, and one of the best answers is that you should cover the code with automated tests (unit tests).

Okay, then: How do you know that your unit tests work?

A test watches the correctness of the SUT, but who watches the watchmen? Should you write some more unit tests to test your unit tests? Is it going to be turtles all the way down?

Obviously, that's not what we do. Then why do we trust unit tests?

I think that there are two different reasons for that:

  • They are easy to review
  • We've seen them fail

Review

The reason that a lot of code fails to do what you think it does, is because it's complicated. Sometimes there are also going to be subtle bugs, but I think that the most common problem is that as the code becomes more involved, it becomes more difficult for you to hold it in your brain. A simple Hello World application is easy to understand. Typical software isn't.

Unit tests tend to be a lot simpler. First of all, unit tests should be deterministic. This means that there should be a clear path through each test case. In other words, a unit test should have a Cyclomatic Complexity of 1.

If you follow the AAA or Four-Phase Test patterns, keep the Cyclomatic Complexity at 1, keep the total line count down, and use good names, you should have a readable test case. Such test code is easy to review for correctness. If you are Pair Programming, you and your partner review the unit test code as you write it. If you use other review mechanisms (e.g. pull requests), the reviewer can review your unit test code. Even if you have no other person reviewing your code, keeping it simple helps you understand what it is that you do. Ultimately, it can't be more error prone than single-handedly writing production code without tests.

Part of the reason why we trust unit tests is because, if written well, they are easy to review for correctness.

See the test fail

Deeply ingrained into proper TDD is the Red/Green/Refactor cycle. It's extremely important to see the test fail. Personally, I'm saved by this rule about once a week. I write a test and run it, and much to my surprise it turns out to be a false negative. Although I've been doing TDD for some ten years, this still happens to me regularly, so I think it's one of those rigid rules you should always follow. Seeing the test fail verifies that the test indeed tests something.

This is also the reason why, if you don't do TDD, but rather write tests after the fact, it becomes extremely important to follow a proper procedure for writing Characterization Tests.

Part of the reason that we trust unit tests is that we've seen them fail. It's like double-entry bookkeeping. The tests keep the SUT in place, and the SUT makes the tests pass.

Append-only tests

Both of the reasons I've provided are focused on the test as it's being created. At that time, you see it fail and you review it for correctness. As time goes by, you should end up with a test suite with lots of tests. Do you ever look at those tests?

You trust them because they were correct when they were created. Are they still correct today?

Well, they probably are if you never again touched them, but every time you modify a test case, you make it just a little less trustworthy. Similar in spirit to the Open/Closed Principle, a test suite should be open for extension, but closed for modification. Trustworthy test suites are append-only.


Page 19 of 40

"Our team wholeheartedly endorses Mark. His expert service provides tremendous value."
Hire me!