web-dev-qa-db-fra.com

Injection de dépendances dans le projet Xunit

Je travaille sur une application Web ASP.Net Core MVC.

Ma solution contient 2 projets: un pour l'application et un deuxième projet, dédié aux tests unitaires.

J'ai ajouté une référence au projet d'application dans le projet Tests.

Ce que je veux faire maintenant, c'est écrire une classe dans le projet Tests qui communiquera avec la base de données via le framework d'entité.

Ce que je faisais dans mon projet d'application était d'accéder à ma classe DbContext via l'injection de dépendance constructeur.

Mais je ne peux pas le faire dans mon projet de tests, car je n'ai pas de fichier Startup.cs. Dans ce fichier, je peux déclarer quels services seront disponibles.

Que puis-je faire pour obtenir une référence à une instance de mon DbContext dans la classe de test?

Merci

9
Bob5421

Vous pouvez implémenter votre propre fournisseur de services pour résoudre DbContext.

public class DbFixture
{
    public DbFixture()
    {
        var serviceCollection = new ServiceCollection();
        serviceCollection
            .AddDbContext<SomeContext>(options => options.UseSqlServer("connection string"),
                ServiceLifetime.Transient);

         ServiceProvider = serviceCollection.BuildServiceProvider();
    }

    public ServiceProvider ServiceProvider { get; private set; }
}

public class UnitTest1:IClassFixture<DbFixture>
{
    private ServiceProvider _serviceProvide;

    public UnitTest1(DbFixture fixture)
    {
        _serviceProvide = fixture.ServiceProvider;
    }

    [Fact]
    public void Test1()
    {
        using (var context = _serviceProvider.GetService<SomeContext>())
        {
        }
    }
}

Mais gardez à l'esprit que l'utilisation d'EF dans le test unitaire n'est pas une bonne idée et il vaut mieux se moquer de DbContext.

L'anatomie d'un bon test unitaire .

8
Mohsen Esmailpour

Vous pouvez utiliser Xunit.DependencyInjection

2
Mr. Pumpkin

Pour les tests unitaires, vous devez vous moquer de votre contexte.

Il existe un excellent paquet de nuget pour se moquer qui s'appelle Moq.

Un peu d'aide pour vous aider à démarrer:

public ClassName : IDisposable
{
    private SomeClassRepository _repository;
    private Mock<DbSet<SomeClass>> _mockSomeClass;

    public ClassName() 
    {
        _mockSomeClass = new Mock<DbSet<SomeClass>>();

        var mockContext = new Mock<IApplicationDbContext>();
        mockContext.SetupGet(c => c.SomeClass).Returns(_mockSomeClass.Object);

        _repository = new SomeClassRepository(mockContext.Object);
    }

    public void Dispose()
    {
        // Anything you need to dispose
    }

    [Fact]
    public void SomeClassTest()
    {
        var someClass = new SomeClass() { // Initilize object };

        _mockSomeClass.SetSource(new[] { someClass });

        var result = _repository.GetSomethingFromRepo( ... );

        // Assert the result
    }
}

Pour les tests d'intégration, vous faites la même chose mais la configuration est la suivante:

_context = new ApplicationDbContext();

Assurez-vous que votre TestClass hérite de IDisposable (TestClass : IDisposable) afin que vous puissiez disposer du contexte après chaque test.

https://xunit.github.io/docs/shared-context

0
Paul Adam