使用SQLite进行内存中测试

在开发项目的过程中,经常需要对数据库进行集成测试,以确保数据库约束正确配置并且能够正常工作。在这种需求下,希望能够找到一个既不会消耗太多处理能力,也不会在测试后留下太多清理工作的解决方案。

在寻找解决方案的过程中,偶然发现了一份文档,它提供了两种方法来实现内存中的数据库测试。经过对比,认为使用内存数据库的方式更适合,因为它不需要引入SQLite作为额外的依赖。

然而,在实际实施过程中,发现内存数据库并不满足需求,主要有两个原因:首先,内存数据库需要一个名称,这样才能在多个测试中使用同一个数据库。这对来说是一个麻烦,因为不希望在每个测试中重新创建数据库。其次,内存数据库并不是一个关系型数据库,它甚至不能算是一个真正的数据库,因为在配置的数据库上下文中,所有的约束都没有被验证。

基于以上原因,决定使用SQLite进行内存中的测试,这样可以复用功能,并且能够检查生成的查询。

设置环境

首先,需要创建一个新的ASP.NET Core MVC项目,并启用个人身份验证。这是因为它已经配置好了数据库上下文,当然,也可以自己创建。

接下来,将创建一个.NET Core控制台项目作为测试项目。在这个测试项目中,将进行大部分的工作。

在测试项目中,需要引用Web应用程序项目,以便可以访问数据库上下文。然后,需要安装一些Nuget包:

  • Microsoft.NET.Test.Sdk (15.7.2) - 用于运行单元测试
  • NUnit (3.10.1) - 选择的测试框架,当然也可以使用任何适合需求的框架。
  • NUnit3TestAdapter (3.10) - 这样ReSharper和Visual Studio就能找到并运行测试。
  • Microsoft.AspNetCore.App - 因为使用了IdentityDbContext,所以需要安装这个包。
  • Microsoft.EntityFrameworkCore.Sqlite (2.1.0) - 用于SQLite的Entity Framework Core支持。

实现

现在已经准备好了所有需要的东西,接下来是实现部分。

按照习惯,在测试项目中,通常会创建一个名为TestUtilities的文件夹,并在其中创建一个名为TestDatabaseContextFactory的静态类。

下面是这个类的代码,已经逐行注释了每个部分的作用。

namespace Test.TestUtilities { using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using WebApplication.Data; public static class TestDatabaseContextFactory { public static ApplicationDbContext CreateDbContext() { DbContextOptionsBuilder contextOptionsBuilder = new DbContextOptionsBuilder(); LoggerFactory loggerFactory = new LoggerFactory(); loggerFactory.AddDebug(); loggerFactory.AddConsole(); SqliteConnectionStringBuilder connectionStringBuilder = new SqliteConnectionStringBuilder { Mode = SqliteOpenMode.Memory }; SqliteConnection connection = new SqliteConnection(connectionStringBuilder.ConnectionString); connection.Open(); contextOptionsBuilder.UseLoggerFactory(loggerFactory); contextOptionsBuilder.UseSqlite(connection); contextOptionsBuilder.EnableSensitiveDataLogging(); ApplicationDbContext context = new ApplicationDbContext(contextOptionsBuilder.Options); context.Database.EnsureCreated(); return context; } } }

有了这个类,现在可以在测试中使用它,如下所示:

namespace Test { using NUnit.Framework; using Test.TestUtilities; using WebApplication.Data; [TestFixture] public class TestingDatabaseCreation { [Test] public void TestCreation() { ApplicationDbContext context = TestDatabaseContextFactory.CreateDbContext(); } } }

尽管这个测试没有断言任何内容,但它仍然会通过,而且如果查看测试运行的输出,将看到所有对数据库执行的查询。

这可能看起来没什么,但它已经成为项目中的一个标准做法,因为尽管单元测试的概念很好,但有时测试需要小而快,但仍然需要执行实际的应用程序逻辑,尤其是当使用SQL时,功能不仅仅存在于应用程序中。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485