Autofixture tests for guard conditions on interface-typed arguments

426 views Asked by At

I'm attempting to use AutoFixture and Autofixture.Idioms to streamline the testing for guard conditions in a constructor. I'm using the following, familiar, almost boilerplate, method to test:

[TestMethod]
public void DependencyConsumerContainsAGuardCondition ( )
{
    var fixture = new Fixture ( );
    var assertion = new GuardClauseAssertion ( fixture );
    assertion.Verify ( typeof ( DependencyConsumer ).GetConstructors ( ) );
}

I have no problems running the test when the constructor for DependencyConsumer is a concrete type:

public interface IDependency { } 

public class ConcreteDependency : IDependency { } 

public class DependencyConsumer
{
    public DependencyConsumer(ConcreteDependency dependency)
    {
        if (dependency == null)
        {
            throw new ArgumentNullException ( "dependency" );
        }
    }
}

When, however, I change the type of the constructor parameter to IDependency, the test fails with the following exception (reformatted for readability)

Test method
    AutomatedTestingPlayground.Playground.DependencyConsumerContainsAGuardCondition
    threw exception: 
Ploeh.AutoFixture.Idioms.GuardClauseException: AutoFixture was unable to
    create an instance for parameter "dependency" of method ".ctor".
Method Signature: Void .ctor(AutomatedTestingPlayground.IDependency)
Declaring Type: AutomatedTestingPlayground.DependencyConsumer
Reflected Type: AutomatedTestingPlayground.DependencyConsumer --->
    Ploeh.AutoFixture.ObjectCreationException: AutoFixture was unable to
    create an instance from AutomatedTestingPlayground.IDependency, most
    likely because it has no public constructor, is an abstract or
    non-public type.

Request path:
      AutomatedTestingPlayground.IDependency

What am I missing in my test setup code? Do I need to mock IDependency explicitly and provide it as a constructor parameter? Given the stated objectives of AutoFixture--"Zero-friction TDD"--and the frequency with which such constructors occur, I'm not sure why I'd need to mock the constructor parameter when it's an abstract type but not when it's a concrete type.

1

There are 1 answers

0
forsvarir On

By default, AutoFixture will only create types that you can new up. Abstract types / interfaces can't be created. If you add in one of the various AutoFixture-Mocking assemblies, they can turn AutoFixture into an AutoMocking container. So, when it detects that you're passing abstract types / interfaces, rather than getting confused it will create Mocks for you.

AutoMocking versions include: