I'm currently testing an Entity Framework's DbContext
using the In-Memory Database.
In order to make tests as atomic as possible, the DbContext
is unique per test-method, and it's populated with initial data needed by each test.
To set the initial state of the DbContext
, I've created a void SetupData
method that fills the context with some entities that I will use in the tests.
The problem with this approach is that the objects that are created during the setup cannot be accessed by the test, because Entity Framework will assign the Ids itself, that are unknown until run-time.
To overcome this problem, I've thought that my SetupData
method could become something like this:
public Fixture SetupData(MyContext context)
{
var fixture = new Fixture();
fixture.CreatedUser = new User();
context.Users.Add(fixture.CreatedUser);
context.SaveChanges();
return fixture;
}
public class Fixture
{
public User CreatedUser { get; set;}
}
As you see, it's returning an instance of what I called "Fixture". (I don't know if the name fits well).
This way, the SetupData
will return an object (Fixture
) with references to the entities. Thus, the test can use the created object. Otherwise, the object will be impossible to identify, since the Id isn't created until the SaveChanges
is called.
My question is:
This is not a bad practice. In fact it is a good approach to create readable Given-When-Then tests. If you consider:
SetupData
methodpublic static MyContextExtensions
{
public static User Given(this MyContext @this, User user)
{
@this.Users.Add(user);
@this.SaveChanges();
return user;
}
public static OtherEntity Given(this MyContext @this, OtherEntity otherEntity)
{
// ...
}
// ...
}
you can then write (a conceptual example, details need to be reworked to match your implementation):
[Test]
public GivenAUser_WhenSearchingById_ReturnsTheUser()
{
var expectedUsername = "username";
var user = _context.Given(AUser.WithName(expectedUsername));
var result = _repository.GetUser(user.Id);
Assert.That(result.Name, Is.EqualTo(expectedUsername));
}
... and similarly for other entities.