Pregunta

I have looked through answers related to this but they don't seem to solve my problem.

I am fairly new unit testing and testing as a whole. I just finished a small web application using ASP.NET Core MVC and I wanted to write tests for the projects. I am using xUnit and Moq.

The project has a business logic layer that contains the business logic for the app.

I am writing tests for the Controllers, but the Controllers contains mostly CRUD operations that use the Repository layer. My tests for the controller involves using an in-memory database since that is the recommended way for ASP.NET Core MVC.

However, I feel what I am doing is no longer unit tests but integration tests since I am testing against a database.

I had thought of writing integration tests for the Repository layer and then unit test for the controllers such that the controllers would not have to check for database operations.

I want to know if this is the right way to go or if there is any other way.

Thanks. [Edit]. Thanks @greg-burghardt for the reply. I made a mistake in my question, I actually meant to write that I have a business logic layer. Also I am using EF, and I believe that takes care of the Repository. My Controllers use the Interface of the required BLL. Example

public class PaymentController : ControllerBase
{
    private readonly IConfiguration _config;
    private readonly IPaymentsBL _paymentsBL;
    private readonly ILogger _logger;

    public PaymentsController(IConfiguration config, IPaymentsBL paymentsBL, ILogger<PaymentsController> logger)
    {
        _config = config;
        _paymentsBL = paymentsBL;
        _logger = logger;
    }
}

And the implementation,

public class PaymentsBL : GenericBL<MPayments>, IPaymentsBL
{
    private readonly WellaPatientDbContext _db;

    public PaymentsBL(WellaPatientDbContext db)
    {
        _db = db;
    }

    public IQueryable<MPayments> GetByPatientId(Guid id)
    {
        return _db.MPayments.Where(x => x.PaymentId == id);
    }
}

Also, you said I am hitting a real database with my tests. I dont understand since I am using an in-memory database.

So if I get you right, tests for the business logic layer is the most important. Thanks

¿Fue útil?

Solución

There are two main problems with the current design that just jump right out at me:

  1. Your repository layer contains business logic. No business logic should reside here. Only persistence logic should exist in your repository (e.g. data mapping and SQL query stuff).

  2. You are hitting a real database with your tests.

Solving these problems so you can write unit tests requires several fixes:

  1. Move the "business logic" into its own set of classes, be they Domain Models or some sort of "service" or "use case" classes

  2. Define interfaces for your repositories, and have your controllers hold references to the repositories with the interface as their type.

  3. Expose a public constructor on your controller classes that accepts a repository by its interface.

Writing tests for persistence logic is not a bad thing. If you use an ORM like NHibernate or Entity Framework sometimes you want tests validating the data mappings.

Writing test for business logic is a terrific idea.

Writing tests for the interaction logic in a controller requires a lot of setup for much less benefit, especially when you've refactored things so your repositories only contain persistence logic, and another set of classes contain the business logic.

Keep the dependencies for the "service" or "use case" related classes light, so setting up unit tests is easy.

Otros consejos

However, I feel what I am doing is no longer unit tests but integration tests since I am testing against a database.

So what, who cares? It doesn't matter whether someone would classify your test as a unit test or an integration test, what matters is is it a useful test?

If it's fast, informative, repeatable and correct, it's a good test. For pointless reasons, people get very hung up on terminology in this industry. It doesn't matter. We write tests because we want a qualitative assurance that we (probably) haven't introduced unexpected deviations in system behaviour, so if you're doing that and someone's giving you grief on the basis "it uses an in-memory database, so technically it's not a unit test", just call it an automated test and keep writing good automated tests.

Licenciado bajo: CC-BY-SA con atribución
scroll top