This post answers a FAQ about ordering of AutoFixture Customizations

With AutoFixture you can encapsulate common Customizations using the Customize method and the ICustomization interface. However, customizations may 'compete' for the same requests in the sense that more than one customization is able to handle a request.

As an example, consider a request for something as basic as IEnumerable<T>. By default, AutoFixture can't create instances of IEnumerable<T>, but more than one customization can.

As previously described the MultipleCustomization handles requests for sequences just fine:

var fixture = new Fixture().Customize(new MultipleCustomization());
var seq = fixture.CreateAnonymous<IEnumerable<int>>();

However, the AutoMoqCustomization can also (sort of) create sequences:

var fixture = new Fixture().Customize(new AutoMoqCustomization());
var seq = fixture.CreateAnonymous<IEnumerable<int>>();

However, in this case, the implementation of IEnumerable<int> is a dynamic proxy, so it's not much of a sequence after all.

Mocking IEnumerable<T>

Here I need to make a little digression on why that is, because this seems to confuse a lot of people. Consider what a dynamic mock object is: it's a dynamic proxy which implements an interface (or abstract base class). It doesn't have a lot of implemented behavior. Dynamic mocks do what we tell them through their configuration APIs (such as the Setup methods for Moq). If we don't tell them what to do, they must fall back on some sort of default implementation. When the AutoMoqCustomization is used, it sets Mock<T>.DefaultValue to DefaultValue.Mock, which means that the default behavior is to return a new dynamic proxy for reference types.

Here's how an unconfigured dymamic proxy of IEnumerable<T> will behave: the interface only has two (very similar) methods:

public interface IEnumerable<out T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}

Via IEnumerable the interface also defines the non-generic GetEnumerator method, but it's so similar to the generic GetEnumerator method that the following discussion applies for both.

When you iterate over IEnumerable<T> using foreach, or when you use LINQ, the first thing that happens is that the GetEnumerator method is called. An unconfigured dynamic mock will respond by returning another dynamic proxy implementing IEnumerator<T>. This interface directly and indirectly defines these methods:

T Current { get; }
 
object IEnumerator.Current { get; }
 
bool MoveNext();
 
void Reset();
 
void Dispose();

Iterating over a sequence will typically start by invoking the MoveNext method. Since the dynamic proxy is unconfigured, it has to fall back to default behavior. For booleans the default value is false, so the return value of a call to MoveNext would be false. This means that there are no more elements in the sequence. Iteration stops even before it begins. In effect, such an implementation would look like an empty sequence.

OK, back to AutoFixture.

Ordering Customizations

Frequently I receive questions like this:

"Creating lists with AutoFixture seems inconsistent. When MultipleCustomization comes before AutoMoqCustomization, lists are popuplated, but the other way around they are empty. Is this a bug?"

No, this is by design. By now, you can probably figure out why.

Still, lets look at the symptoms. Both of these tests pass:

[Fact]
public void OnlyMultipleResolvingSequence()
{
    var fixture = new Fixture().Customize(new MultipleCustomization());
    var seq = fixture.CreateAnonymous<IEnumerable<int>>();
    Assert.NotEmpty(seq);
}
 
[Fact]
public void OnlyAutoMoqResolvingSequence()
{
    var fixture = new Fixture().Customize(new AutoMoqCustomization());
    var seq = fixture.CreateAnonymous<IEnumerable<int>>();
    Assert.Empty(seq);
}

Notice that in the first test, the sequence is not empty, whereas in the second test, the sequence is empty. This is because the MultipleCustomization produces a 'proper' sequence, while the AutoMoqCustomization produces a dynamic proxy of IEnumerable<int> as described above. At this point, this should hardly be surprising.

The same obvervations can be made when both Customizations are in use:

[Fact]
public void WrongOrderResolvingSequence()
{
    var fixture = new Fixture().Customize(
        new CompositeCustomization(
            new AutoMoqCustomization(),
            new MultipleCustomization()));
 
    var seq = fixture.CreateAnonymous<IEnumerable<int>>();
 
    Assert.Empty(seq);
}
 
[Fact]
public void CorrectOrderResolvingSequnce()
{
    var fixture = new Fixture().Customize(
        new CompositeCustomization(
            new MultipleCustomization(),                    
            new AutoMoqCustomization()));
 
    var seq = fixture.CreateAnonymous<IEnumerable<int>>();
 
    Assert.NotEmpty(seq);
}

Both of these tests also pass. In the first test the sequence is empty, and in the second it contains elements. This is because the first Customization 'wins'.

In general, a Customization may potentially be able to handle a lot of requests. For instance, the AutoMoqCustomization can handle all requests for interfaces and abstract base classes. Thus, multiple Customizations may be able to handle a request, so AutoFixture needs a conflict resolution strategy. That strategy is simply that the first Customization which can handle a request gets to do that, and the other Customizations are never invoked. You can use this feature to put specific Customizations in front of more catch-all Customizations. That's essentially what happens when you put MultipleCustomization in front of AutoMoqCustomization.



Wish to comment?

You can add a comment to this post by sending me a pull request. Alternatively, you can discuss this post on Twitter or Google Plus, or somewhere else with a permalink. Ping me with the link, and I may add it as a comment.

Published

Tuesday, 31 July 2012 16:31:11 UTC

Tags



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