2014-02-26 44 views
0

我正在使用Autofixture來生成我的測試模型,但在一個實例中它說我的模型有一個我無法找到的循環引用。發生故障的模型是類RepresentationExpense和我能想到的是它是涉及到繼承的東西,因爲Expense類不具有相同的問題的唯一的事情:找不到Autofixture循環引用

public class RepresentationExpense : Expense 
{ 
    public string GuestName { get; private set; } 
    public string GuestCompany { get; private set; } 

    public RepresentationExpense(ExpenseId id, ExpenseReportId reportId, EmployeeId employeeId, string description, Payment payment, DateTime created, PaymentMethod paymentMethod, ReceiptId receiptId, string guestName, string guestCompany, string comment = null) 
     : base(id, reportId, employeeId, description, payment, created, paymentMethod, CategoryType.Representation, receiptId, comment) 
    { 
     Verify.ArgumentNotNull(guestName, "guestName"); 
     Verify.ArgumentNotNull(guestCompany, "guestCompany"); 

     GuestName = guestName; 
     GuestCompany = guestCompany; 
    } 
} 

public class Expense 
{ 
    public ExpenseId Id { get; private set; } // simple wrapper for long 
    public ExpenseReportId ReportId { get; private set; } // simple wrapper for long 
    public EmployeeId EmployeeId { get; private set; } // simple wrapper for long 
    public Payment Payment { get; private set; } 
    public DateTime Created { get; private set; } 
    public PaymentMethod PaymentMethod { get; private set; } // enum 
    public CategoryType CategoryType { get; private set; } // enum 
    public ReceiptId ReceiptId { get; private set; } // simple wrapper for long 
    public string Description { get; private set; } 
    public string Comment { get; private set; } 

    public Expense(ExpenseId id, ExpenseReportId reportId, EmployeeId employeeId, string description, Payment payment, DateTime created, PaymentMethod paymentMethod, CategoryType categoryType, ReceiptId receiptId, string comment = null) 
    { 
     Verify.ArgumentNotDefault(id, "id"); 
     Verify.ArgumentNotDefault(reportId, "reportId"); 
     Verify.ArgumentNotDefault(employeeId, "employeeId"); 
     Verify.ArgumentNotDefault(created, "created"); 
     Verify.ArgumentNotNull(categoryType, "category"); 
     Verify.ArgumentNotNull(payment, "payment"); 
     Verify.ArgumentNotNull(paymentMethod, "paymentMethod"); 
     Verify.ArgumentNotDefault(receiptId, "receipt"); 
     Verify.ArgumentNotNull(description, "description"); 
     Verify.Argument(receiptId != ReceiptId.Unassigned, "Must have an existing report"); 
     Verify.Argument(reportId != ExpenseReportId.Unassigned, "Must have an existing report"); 

     Id = id; 
     ReportId = reportId; 
     EmployeeId = employeeId; 
     Created = created; 
     CategoryType = categoryType; 
     Payment = payment; 
     PaymentMethod = paymentMethod; 
     ReceiptId = receiptId; 
     Description = description; 
     Comment = comment; 
    } 
} 

public sealed class Payment 
{ 
    public Money Money { get; private set; } // simple class 
    public ExchangeRate ExchangeRate { get; private set; } // simple class 
    public DateTime Date { get; private set; } 

    public Payment(Money money, ExchangeRate exchangeRate, DateTime date) 
    { 
     Verify.ArgumentNotNull(money, "money"); 
     Verify.ArgumentNotNull(exchangeRate, "exchangeRate"); 
     Verify.ArgumentNotDefault(date, "date"); 
     Verify.Argument(money.Currency.Name == exchangeRate.Currency.Name, "Currency must be the same for money and exchange rate"); 
     Verify.Operation(date <= DateTime.Now, "You cannot create a payment in the future"); 

     Money = money; 
     ExchangeRate = exchangeRate; 
     Date = date; 
    } 
} 

以下是錯誤消息。不過,我並不完全遵循上述路徑。

Ploeh.AutoFixture.Idioms.GuardClauseException : AutoFixture was unable to create an instance for parameter "payment" of method ".ctor". 
Method Signature: Void .ctor(BLL.Modules.Expenses.Models.ExpenseId, BLL.Modules.Expenses.Models.ExpenseReportId, BLL.Modules.Expenses.Models.EmployeeId, System.String, BLL.Modules.Expenses.Models.Payment, System.DateTime, BLL.Modules.Expenses.Models.PaymentMethod, BLL.Modules.Expenses.Models.ReceiptId, System.String, System.String, System.String) 
Declaring Type: BLL.Modules.Expenses.Models.RepresentationExpense 
Reflected Type: BLL.Modules.Expenses.Models.RepresentationExpense 
    ----> Ploeh.AutoFixture.ObjectCreationException : AutoFixture was unable to create an instance of type System.RuntimeType 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. 
    Path: 
     BLL.Modules.Expenses.Models.Payment --> 
     BLL.Modules.Expenses.Models.Payment payment --> 
     BLL.Modules.Expenses.Models.Payment 
Result StackTrace: 
at Ploeh.AutoFixture.Idioms.GuardClauseAssertion.GetParameters(IMethod method) 
at Ploeh.AutoFixture.Idioms.GuardClauseAssertion.GetParameterGuardCommands(IMethod method) 
at Ploeh.AutoFixture.Idioms.GuardClauseAssertion.VerifyNormal(IMethod method) 
at Ploeh.AutoFixture.Idioms.GuardClauseAssertion.Verify(IMethod method, Boolean isReturnValueIterator) 
at Ploeh.AutoFixture.Idioms.GuardClauseAssertion.Verify(ConstructorInfo constructorInfo) 
at Ploeh.AutoFixture.Idioms.IdiomaticAssertion.Verify(ConstructorInfo[] constructorInfos) 
at Ploeh.AutoFixture.Idioms.IdiomaticAssertion.Verify(Type type) 
at WorkxoneUnitTests.TestBase`1.AssertGuardClausesForType() in c:\Code\Comenxa\WorkxoneUnitTests\TestBase.cs:line 58 
at WorkxoneUnitTests.BLL.Modules.Expenses.Models.RepresentationExpenseTests.Guards_are_asserted() in c:\Code\Comenxa\WorkxoneUnitTests\BLL\Modules\Expenses\Models\RepresentationExpenseTests.cs:line 24 
--ObjectCreationException 
at Ploeh.AutoFixture.Kernel.ThrowingRecursionHandler.HandleRecursiveRequest(Object request, IEnumerable`1 recordedRequests) 
at Ploeh.AutoFixture.Kernel.RecursionGuard.HandleRecursiveRequest(Object request) 
at Ploeh.AutoFixture.Kernel.RecursionGuard.Create(Object request, ISpecimenContext context) 
at Ploeh.AutoFixture.Fixture.Create(Object request, ISpecimenContext context) 
at Ploeh.AutoFixture.Kernel.SpecimenContext.Resolve(Object request) 
at Ploeh.AutoFixture.Idioms.SpecimenBuilderComposer.CreateAnonymous(ISpecimenBuilder builder, Object request) 
at Ploeh.AutoFixture.Idioms.GuardClauseAssertion.GetParameters(IMethod method) 
+1

定製自動混合物你看過這個https://github.com/AutoFixture/AutoFixture/issues/226嗎? – wiero

+0

我沒有,但它導致我真正的問題。原來是NUnit引起的問題,我錯誤地認爲它會爲每個測試實例化一個新的測試類,允許我使用構造函數進行fixture初始化。 –

回答

1

我設法在構造函數中拋出異常時重現。您可以調試您的代碼並檢查哪個對象不通過「驗證部分」。然後你可以嘗試freeze有效的對象,它將在測試中使用。或者你可以用ISpecimenBuilder

+0

這是有道理的,因爲另一個測試聲稱警衛在構造函數中檢查,並且夾具意外地在測試之間重用。 –