Question

I have the following class and test. I want to test passing a null value as a parameter to the constructor and are expecting an ArgumentNullException. But since I use the Autofixture's CreateAnonymous method I get a TargetInvocationException instead.

What is the correct way to write those kinds of tests?

public sealed class CreateObject : Command {
    // Properties
    public ObjectId[] Ids { get; private set; }
    public ObjectTypeId ObjectType { get; private set; }
    public UserId CreatedBy { get; private set; }

    // Constructor
    public CreateObject(ObjectId[] ids, ObjectTypeId objectType, UserId createdBy) {
      Guard.NotNull(ids, "ids");
      Guard.NotNull(objectType, "objectType");
      Guard.NotNull(createdBy, "createdBy");

      Ids = ids;
      ObjectType = objectType;
      CreatedBy = createdBy;
    }
}

[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void constructor_with_null_ids_throw() {
    fixture.Register<ObjectId[]>(() => null);
    fixture.CreateAnonymous<CreateObject>();
}
Was it helpful?

Solution

IMO, Ruben Bartelink's comment is the best answer.

With AutoFixture.Idioms, you can do this instead:

var fixture = new Fixture();
var assertion = new GuardClauseAssertion(fixture);
assertion.Verify(typeof(CreateObject).GetConstructors());

The Verify method will provide you with a quite detailed exception message if any constructor argument in any constructor is lacking a Guard Clause.


FWIW, AutoFixture extensively uses Reflection, so I don't consider it a bug that it throws a TargetInvocationException. While it could unwrap all TargetInvocationException instances and rethrow their InnerException properties, that would also mean disposing of (potentially) valuable information (such as the AutoFixture stack trace). I've considered this, but don't want to take AutoFixture in that direction, for exactly that reason. A client can always filter out information, but if information is removed prematurely, no client can get it back.

If you prefer the other approach, it's not too hard to write a helper method that unwraps the exception - perhaps something like this:

public Exception Unwrap(this Exception e)
{
    var tie = e as TargetInvocationException;
    if (tie != null)
        return tie.InnerException;
    return e;
}

OTHER TIPS

I came across this while I was searching for something similar. I would like to add that, combined with automoqcustomization and xunit, below code also works and its much cleaner.

    [Theory, AutoMoqData]
    public void Constructor_GuardClausesArePresent(GuardClauseAssertion assertion)
    {
        assertion.Verify(typeof(foo).GetConstructors());
    }

You just need to create the AutoMoqData attribute as follows.

    public class AutoMoqDataAttribute : AutoDataAttribute
    {
        public AutoMoqDataAttribute() : base(() => new Fixture().Customize(new AutoMoqCustomization()))
        {

        }
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top