0

The Decorator pattern demonstrates how we can extend the behaviour of a component without modifying the underlying implementation. But this means I have two components that implement the same interface. Is there a way to Register these in AutoFixture so that I can still refer to my component polymorphically as its interface?

A code example my help with my meaning. Let's assume I want to decorate an IComponent with a LoggingComponent

interface IComponent
{
    void DoStuff();
}

class Component : IComponent
{
    public void DoStuff()
    {
        // Do something amazing!
    }
}

class LoggingComponent : IComponent
{
    private readonly IComponent _Component;

    public LoggingComponent(IComponent Component)
    {
        _Component = Component;
    }

    public void DoStuff()
    {
        Console.WriteLine("Calling DoStuff()");
        _Component.DoStuff();
    }
}

How would I go about both registering LoggingComponent as an IComponent and creating a LoggingComponent without a circular dependency?

What's the alternative to registering LoggingComponent this way:

_fixture.Register<IComponent>(_fixture.Create<LoggingComponent>);

And then trying to create an instance of IComponent using this code:

var Component = _fixture.Create<IComponent>();

Which obviously results in this ObjectCreationException exception being thrown:

AutoFixture was unable to create an instance of type Ploeh.AutoFixture.Kernel.SeededRequest because the traversed object graph contains a circular reference. Information about the circular path follows below. This is the correct behavior when a Fixture is equipped with a ThrowingRecursionBehavior, which is the default. This ensures that you are being made aware of circular references in your code. Your first reaction should be to redesign your API in order to get rid of all circular references. However, if this is not possible (most likely because parts or all of the API is delivered by a third party), you can replace this default behavior with a different behavior: on the Fixture instance, remove the ThrowingRecursionBehavior from Fixture.Behaviors, and instead add an instance of OmitOnRecursionBehavior.

Owain Williams
  • 2,387
  • 17
  • 22
  • 1
    Why do you want to do this? It almost sounds like you're trying to use AutoFixture as a *DI Container*, which it [quite explicitly wasn't designed to be](https://github.com/AutoFixture/AutoFixture/wiki/FAQ#is-autofixture-a-dependency-injection-container-it-has-generic-create-and-register-methods). – Mark Seemann Jun 29 '15 at 19:06
  • I'm thinking of AutoFixture as a DI Container for my tests. My reasoning being that in the production code I'll use a DI Container and just ask for an `IComponent`, so I wanted to write my tests to simulate the same, e.g. ensure I can code against the interface rather than the concrete type. Your FAQ says that "AutoFixture acts as its own micro-Container, but its purpose is not to be a general-purpose DI Container", I thought I could use AutoFixture as a micro-Container to simulate a DI Container in my tests. Perhaps I'll just have to stick with an explicit cast. – Owain Williams Jun 30 '15 at 10:43
  • 1
    Even if you think of AutoFixture as a DI Container, most DI Containers on .NET don't natively support the Decorator pattern. Instead, you'll have to jump through all sorts of hoops in order to enable that pattern; [my book's](http://amzn.to/12p90MG) part 4 explains how to do that for various containers. You can use the same sort of approach with AutoFixture's `Register` method. – Mark Seemann Jun 30 '15 at 11:03
  • 1
    In any case, I don't recommend that approach. If you ask for `IComponent` and you get an entire object graph back, then what's your System Under Test? – Mark Seemann Jun 30 '15 at 11:05
  • Thanks for your comments. I have your book Mark, it's excellent. As it happens, my DI container ([Simple Injector](https://simpleinjector.readthedocs.org/en/latest/advanced.html#decorators)) does support Decorators. I'll have a think about what it is I'm trying to test. I wanted to code against the interface, not the concrete type. Then I was going to call Verify methods on my mock injected objects (e.g the base `IComponent` or `ILogger` object, etc.) to ensure my SUT worked as expected. But maybe I need to refer to a concrete type in a test. – Owain Williams Jun 30 '15 at 12:48
  • 1
    Perhaps this helps: http://stackoverflow.com/a/1465896/126014 – Mark Seemann Jun 30 '15 at 12:57

1 Answers1

3

You need to freeze the IComponent first.

Then, AutoFixture will re-use the same frozen IComponent instance when creating the LoggingDecorator class.

Here are 2 ways of doing this:

Using AutoFixture with Auto Mocking:

PM> Install-Package AutoFixture.AutoMoq

[Fact]
public void UsingAutoFixtureAutoMoq()
{
    var fixture = new Fixture()
        .Customize(new AutoMoqCustomization());
    var expected = fixture.Freeze<Mock<IComponent>>().Object;
    var decorator = fixture.Create<LoggingComponent>(); 

    var actual = decorator.Component;

    Assert.Equal(expected, actual);
}

Using AutoFixture with Auto Mocking and xUnit.net data theories:

PM> Install-Package AutoFixture.Xunit
PM> Install-Package AutoFixture.AutoMoq

[Theory, TestConventions]
public void UsingAutoFixtureAutoMoqWithXunitTheories(
    [Frozen]Mock<IComponent> inner,
    LoggingComponent decorator)
{
    var expected = inner.Object;
    var actual = decorator.Component;
    Assert.Equal(expected, actual);
}

TestConventions attribute class is defined as:

internal class TestConventionsAttribute : AutoDataAttribute
{
    internal TestConventionsAttribute()
        : base(
            new Fixture().Customize(
                new AutoMoqCustomization()))
    {
    }
}

Note: To compile and run the above test(s), add an Inspection Property for IComponent to LoggingDecorator.

Nikos Baxevanis
  • 10,868
  • 2
  • 46
  • 80
  • That means I'm referring to my decorated component as a `LoggingComponent` instead of an `IComponent`, I guess there's no way of referring to my decorated component polymorphically as an `IComponent` without explicitly casting it first? – Owain Williams Jun 29 '15 at 16:09
  • The SUT in my example would be the `LoggingComponent`. So I could just write tests against the concrete type, but I wanted to ensure the component could be used as an `IComponent` and force me to code against the interface, therefore ensure adherence to the [Liskov Substitution Principle](https://en.wikipedia.org/wiki/Liskov_substitution_principle). – Owain Williams Jun 30 '15 at 10:48
  • If the SUT is the `LoggingComponent`, the above test(s) should be just fine. – Both create an instance of the `IComponent` and its `LoggingComponent` decorator, while making sure that you get back the *same* decorated `IComponent` instance with the one being used by the decorated class. – Nikos Baxevanis Jun 30 '15 at 11:12
  • I see what you're saying. I can test my `LoggingComponent` concrete type, but I wanted to test that an appropriately decorated `IComponent` logged correctly. I wasn't intending on creating a full object graph, just a mocked `IComponent` and whatever other mock objects the `LoggingComponent` needed and checking my SUT worked as expected by verifying calls on these mock objects. Maybe I'm going about this the wrong way. I'll give your comments and answer some more thought. – Owain Williams Jun 30 '15 at 12:54