0

I've been working on an implementation of a service, and have found that there are a number of operations where I need to read from a database to provide a caller with certain data or objects.

In-line with the .NET DI system, I have a DbContext injected into the classes that need to retrieve data. Something like the following:

public class RepositoryImpl
{
  public RepositoryImpl(DbContext<Database> context)
  {
    _context = context;
  }

  // later

  public DtoClass GetById(string id)
  {
    return _context.Entities.FirstOrDefault(entity => entity.Id == id);
  }
}

However, to validate that the logic for retrieving the Entity by ID, I want to write automated tests. But from what I've read (for example: here), it looks like automated testing isn't really discussed for the integration point between application logic and data sources.

Is the only way to write effective automated tests for classes that inject the DbContext to provider in-memory data as a fake, then? That reads to me like an integration test unless you define a "unit" as both the DbContext and logic to interact with it, but that seems wrong to me.

What are the common practices or strategies for verifying this logic?

New contributor
Lily Smith is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
7
  • What do you actually want to validate? In order to be confident in your IQueriable, you need test that it is lowerable to SQL. And the only way to trigger that is to test with your database provider in the loop. Hence why the page you linked recommends the use of integration tests against your production database. Commented Oct 20 at 1:56
  • Hence the recommendation to limit the classes that access the DbContext to just your repositories, and have everything else use methods that abstract the linq, such that you can mock them. Commented Oct 20 at 1:58
  • This code is only meanigfully testable with an integration test, as repositories often are. This is not bad, as there are some in-memory DB implementations, that can help with test fixture. Failing that, there are in-process options. Commented Oct 20 at 4:33
  • Can you please explain why you interpret injecting a fake to mean that it is therefore an integration test? I was expecting the opposite conclusion. The root of your question may find itself in what kind of tests you are trying to run, and how you define unit and integration tests. Commented Oct 20 at 8:15
  • @Flater it is a good fake. A real in-process relational DB with complete implementation. I other words, the only thing that is much different from production is test data in that DB. Commented Oct 20 at 8:23

1 Answer 1

3

it looks like automated testing isn't really discussed for the integration point between application logic and data sources.

This is incorrect.

In unit testing, you won't have access to the database. But unit tests is only one of numerous test types. Smoke tests, system tests, load tests, stress tests and some integration and functional tests would access the database.

Be aware, however. Introducing database in your automated tests have drawbacks, especially:

  • Performance. Don't expect to run thousands of tests per second like you do with unit tests, if you depend on a database.
  • Conflicts between tests, especially when ran in parallel. This can usually be circumvented by using transitions that are automatically rolled back at the end of the test.
  • Infrastructure. Essentially, ops need to ensure the test machines can access a database, and the database should always be available when tests are running.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.