Xunit项目的依赖注入

发布于 2025-02-07 23:08:57 字数 397 浏览 2 评论 0原文

我正在研究ASP.NET Core MVC Web应用程序。

我的解决方案包含2个项目:

  • 一个用于应用程序的项目和
  • 第二个项目,专用于单位测试(XUNIT)。

我在测试项目中添加了对应用程序项目的参考。

我现在想做的是在Xunit测试项目中编写一类,该项目将通过实体框架与数据库进行通信。

我在应用程序项目中正在做的是通过构造依赖依赖注入访问我的dbContext类。

但是我无法在测试项目中这样做,因为我没有startup.cs文件。在此文件中,我可以声明将有哪些服务可用。

那么,我该怎么做才能在测试类中获取对我的dbContext实例的引用?

I am working on an ASP.Net Core MVC Web application.

My Solution contains 2 projects:

  • One for the application and
  • A second project, dedicated to unit tests (XUnit).

I have added a reference to the application project in the Tests project.

What I want to do now is to write a class in the XUnit Tests project which will communicate with the database through entity framework.

What I was doing in my application project was to access to my DbContext class through constructor dependency injection.

But I cannot do this in my tests project, because I have no Startup.cs file. In this file I can declare which services will be available.

So what can I do to get a reference to an instance of my DbContext in the test class?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

回忆那么伤 2025-02-14 23:08:57

您可以实现自己的服务提供商来解决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 _serviceProvider;

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

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

但是,在单元测试中使用EF在您的脑海中却不是一个好主意,最好嘲笑dbcontext。

良好单位测试的解剖结构

You can implement your own service provider to resolve 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 _serviceProvider;

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

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

But bear in your mind using EF inside a unit test is not a good idea and it's better to mock DbContext.

The Anatomy of Good Unit Testing

猫腻 2025-02-14 23:08:57

您可以使用

染柒℉ 2025-02-14 23:08:57

对于单元测试,您需要嘲笑您的上下文。

有一个很棒的nuget软件包用于嘲笑,称为签名。

有一些帮助使您开始的帮助:

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
    }
}

对于集成测试,您可以执行同样的事情,但是设置是:

_context = new ApplicationDbContext();

确保您的testClassiDisposabletestClass:idisposable:idisposable < /code>),以便您可以在每个测试之后处置上下文。

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

For unit tests you need to mock your context.

There is a great nuget package for mocking that is called Moq.

Some help to get you started:

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
    }
}

For integration tests you do the same thing but the setup is:

_context = new ApplicationDbContext();

Make sure that your TestClass inherits from IDisposable (TestClass : IDisposable) so that you can dispose the context after each test.

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

云醉月微眠 2025-02-14 23:08:57

您可以使用Microsoft.entityFrameworkCore.inmemory

DbContextOptionsBuilder&lt; dbContext&gt;()

var _dbContextOptions = new = new DbContext(_DBContextOptions);

You can to use package Microsoft.EntityFrameworkCore.InMemory

var _dbContextOptions = new DbContextOptionsBuilder<DbContext>().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options;

And then

var context = new DbContext(_dbContextOptions);

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文