I am making a MSTest project of my app created with Data-driven strategy. Now, I would like to mock the database using interface. But the DB Entity is automatically generated, so my modification for DI will be destroyed when entity was updated.
Should I give up testing with a mock and access the actual DB every time?
(Update 2022/01/28) I am thinking for compromise: rather than accessing DB entity directly on the model, I would make service facades that on the one class handles DB (for production usage), while the other just works itself.
Short crude examples here:
public interface IMemberDatabaseService
{
Member Search(string name);
void Create(MemberModel model);
}
public class MemberDatabaseService : IMemberDatabaseService, IDisposable
{
private AutomaticallyGeneratedDBContext Con = new();
public Member Search(string name)
{
return Con.Member.SingleOrDefault(mb => mb.Name == name);
}
public void Create(MemberModel model)
{
Member member = Convert(model);
Con.Member.Add(model);
Con.SaveChanges();
}
private static Member Convert(MemberModel model)
{
// convert model to Member
}
// Dispose pattern here...
}
public class MemberTestService : IMemberDatabaseService, IDisposable
{
private static List<Member> MemberList = new();
public Member Search(string name)
{
return name == "John Doe" ? new Member{ Name = name, ...} : null;
}
public void Create(MemberModel model)
{
Member member = Convert(model); // convert model to Member
MemberList.Add(model);
}
private static Member Convert(MemberModel model)
{
// convert model to Member
}
// Dispose pattern here...
}
The drawback is I cannot test the LINQ portion or conflict handling without connecting the DB.
You will need to add specific detail about what your implementation looks like.
Mocking DbContexts/DbSets is possible, but arguably a fair bit of work and ugly to work with. Unit testing is one good argument for implementing a Repository pattern to serve as a boundary for the mocks, but if you're past the point where something like that can be implemented, a simpler solution can be to point your DbContext at an in-memory database that is seeded with suitable test data.
The downside is that most test frameworks accommodate running tests in parallel and not necessarily in order so you need to ensure each test's data row dependencies are safely isolated from each other to ensure you don't get intermittent failures due to one test tampering with data that another test relies on.