无效构造函数参数的自动混合测试

arw*_*dab 11 autofixture

我有以下课程和考试.我想测试将null值作为参数传递给构造函数并期待一个ArgumentNullException.但是因为我使用了Autofixture的CreateAnonymous方法,所以我得到了一个TargetInvocationException.

编写这些测试的正确方法是什么?

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>();
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*ann 13

IMO,Ruben Bartelink的评论是最好的答案.

使用AutoFixture.Idioms,您可以改为:

var fixture = new Fixture();
var assertion = new GuardClauseAssertion(fixture);
assertion.Verify(typeof(CreateObject).GetConstructors());
Run Code Online (Sandbox Code Playgroud)

如果任何构造函数中的任何构造函数参数缺少Guard子句,Verify方法将为您提供非常详细的异常消息.


FWIW,AutoFixture广泛使用Reflection,所以我不认为它是一个它抛出的bug TargetInvocationException.虽然它可以解包所有TargetInvocationException实例并重新抛出其InnerException属性,但这也意味着处置(可能)有价值的信息(例如AutoFixture堆栈跟踪).我已经考虑过这个问题了,但是出于这个原因,我不想在这个方向上采用AutoFixture.客户端总是可以过滤掉信息,但如果过早删除信息,则客户端无法将其恢复.

如果您更喜欢其他方法,那么编写一个解包异常的辅助方法并不是很难 - 可能是这样的:

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