Vida
Vida

Reputation: 109

I am facing exception "AutoFixture.ObjectCreationExceptionWithPath" With AutoFixture in EF Core Code First Approach

I am currently using EF Core Code First Approach and I have the following domain classes:

public class Employee
{
  // several properties such as Name, Address, ...

  public Guid? CompanyId { get; set; }

  public Company Company {get;set;}

}

 public class Company
{
   public Guid? CompanyId { get; set; }

   public IEnumerable<Employee>? Employee{ get; set; }
}

I am using XUnit and Autofixture to create my tests:

public class MyTest{

 private readonly Fixture _fixture = new Fixture();

[Fact]
public void TestMethod(){

var employee =  _fixture.Create<Employee>();
...
}

}

The above _fixture.Create gives me the below error:

Message: AutoFixture.ObjectCreationExceptionWithPath : AutoFixture was unable to create an instance of type AutoFixture.Kernel.FiniteSequenceRequest because the traversed object graph contains a circular reference.

I need to include the: public Company Company {get;set;} in the Employee class to make it a foreign key. But if I remove that line, it works fine.

Many links online suggests the below solution - but I wanted to know if there is another way around instead of removing the ThrowingRecursion behavior:

fixture.Behaviors.OfType<ThrowingRecursionBehavior>().ToList()
    .ForEach(b => fixture.Behaviors.Remove(b));
fixture.Behaviors.Add(new OmitOnRecursionBehavior());

Upvotes: 3

Views: 1828

Answers (1)

Serhii Shushliapin
Serhii Shushliapin

Reputation: 2708

This might not be the direct answer to your question what to do with AutoFixture... There are numerous options possible:

  1. you can customize AF as suggested in your question
  2. you may configure EF Core foreign keys without using navigation property
  3. or, you may change your code design to be more DDD style. This may help you to avoid any AF customizations but may also be a bit more time consuming...

The first step to make your code more 'DDD-ish' is to close public setters and start managing your entities via constructors or method parameters. This would let AF create your classes without circular dependencies. EF Core is also smart enough and is able to set values into protected members. The code may look like the following:

public class Employee
{
  // closed setter, no AF issues, EF Core will still work
  public Company Company {get; protected set;} 

  // Some functionality from your domain model
  public void JoinCompany(Company company)
  {
      // do smth here.
      Company = company
  }

  public void LeaveCompany()
  {
      Company = null;
  }
}

Or, from Company perspective, the API may look like the following (again, I do not know your domain model, so just prototyping):

public class Company
{
    private List<Employee> _employee = new List<Employee>();

    public IReadOnlyCollection<Employee> Employee => _employee;

    public void EnrollEmployee(Employee employee)
    {
        _employee.Add(employee);
    }
}

Some code samples can be found here: https://github.com/vkhorikov/DddAndEFCore/blob/master/src/App/Student.cs

Upvotes: 2

Related Questions