Greg Gum
Greg Gum

Reputation: 37909

How to Mock an entity manager

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

Answers (1)

David
David

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:

  1. Create a mock with known behavior for the one method being invoked (GetFileRowEntitiesToProcess()).
  2. Inject that mock into this containing object being tested.

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

Related Questions