Reputation: 109
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
Reputation: 2708
This might not be the direct answer to your question what to do with AutoFixture... There are numerous options possible:
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