Reputation: 37909
Am new to unit testing, and just getting started writing unit tests for an existing code base.
I would like to write a unit test for the following method of a class.
public int ProcessFileRowQueue()
{
var fileRowsToProcess = this.EdiEntityManager.GetFileRowEntitiesToProcess();
foreach (var fileRowEntity in fileRowsToProcess)
{
ProcessFileRow(fileRowEntity);
}
return fileRowsToProcess.Count;
}
The problem is with GetFileRowEntitiesToProcess();
The Entity Manager is a wrapper around the Entity Framework Context. I have searched on this and found one solution is to have a test database of a known state to test with. However, it seems to me that creating a few entities in the test code would yield more consistent test results.
But as it exists, I don't see a way to mock the Manager without some refactoring.
Is there a best practice for resolving this? I apologize for this question being a bit naïve, but I just want to make sure I go down the right road for the rest of the project.
Upvotes: 0
Views: 385
Reputation: 218837
I'm hearing two questions here:
Should I mock EdiEntityManager?
Yes. It's a dependency external to the code being tested, its creation and behavior are defined outside of that code. So for testing purposes a mock with known behavior should be injected.
How can I mock EdiEntityManager?
That we can't know from the code posted. It depends on what that type is, how it's created and supplied to that containing object, etc. To answer this part of the question, you should attempt to:
GetFileRowEntitiesToProcess()
).For either of these efforts, discover what may prevent that from happening. Each such discovery is either going to involve learning a little bit more about the types and the mocks, or is going to reveal a need for refactoring to allow testability. The code posted doesn't reveal that.
As an example, suppose EdiEntityManager
is created in the constructor:
public SomeObject()
{
this.EdiEntityManager = new EntityManager();
}
That would be something that prevents mocking because it gets in the way of Step 2 above. Instead, the constructor would be refactored to require rather than instantiate:
public SomeObject(EntityManager ediEntityManager)
{
this.EdiEntityManager = ediEntityManager;
}
That would allow a test to supply a mock, and conforms with the Dependency Inversion Principle.
Or perhaps EntityManager
is too concrete a type and difficult to mock/inject, then perhaps the actual type should be an interface which EntityManager
defines. Worst case scenario with this problem could be that you don't control the type at all and simply need to define a wrapper object (which itself has a mockable interface) to enclose the EntityManager
dependency.
Upvotes: 2