推荐的内存 Sqlite 数据库种子方式是什么?

问题描述 投票:0回答:3

我正在尝试在我的 C# 应用程序上实现内存中的 Sqlite 数据库以用于测试目的。我想在启动期间为数据库播种,以便我可以控制赛普拉斯端到端测试中使用的数据。根据我的在线研究,我发现有两种方法可以做到这一点。

第一个是使用

DbContext.AddRange()
方法将数据添加到上下文中,如 Mircosoft 的示例此处所示。

第二个是在 OnModelCreating() 方法中,您可以在其中将数据添加到模型中,如下所示:

modelBuilder.Entity<Book>().HasData(
    new Book { BookId = 1, AuthorId = 1, Title = "Hamlet" },
    new Book { BookId = 2, AuthorId = 1, Title = "King Lear" },
    new Book { BookId = 3, AuthorId = 1, Title = "Othello" }
);

Microsoft 文档:https://learn.microsoft.com/en-us/ef/core/modeling/data-seeding

无论哪种情况,我相信你也必须使用

context.Database.EnsureCreated();
,但我不知道该把它放在哪里。

用测试数据为我的数据库播种的推荐方法是什么?

c# sqlite entity-framework-core cypress
3个回答
4
投票

从测试的角度来看,内存中似乎是一个限制因素,因为 Cypress 无法直接与 EF 纯粹在其内存空间中创建的数据库进行互操作。

但是您可以通过 node-sqlite3 创建基于文件的 Sqlite 数据库,您可以通过调用 Cypress 任务来播种。

这里有一个示例配方 server-communication__seeding-database-in-node

这在

cy.task('seed:db')
 中设置了 
cypress.config.js

const { defineConfig } = require('cypress')

const { seed } = require('./server/db')

module.exports = defineConfig({
  e2e: {
    baseUrl: 'http://localhost:7082',
    supportFile: false,
    setupNodeEvents (on, config) {
      on('task', {
        'seed:db' (data) {
          return seed(data).then(() => {
            return data
          })
        },
      })
    },
  },
})

在Cypress配方中,

./server/db.js
需要来自node-sqlite3包的一些代码,而不是它当前拥有的代码(使用json文件作为数据库),例如

const sqlite3 = require('sqlite3').verbose();
const db = new sqlite3.Database(':memory:');

db.serialize(() => {
    db.run("CREATE TABLE lorem (info TEXT)");

    const stmt = db.prepare("INSERT INTO lorem VALUES (?)");
    for (let i = 0; i < 10; i++) {
        stmt.run("Ipsum " + i);
    }
    stmt.finalize();

    db.each("SELECT rowid AS id, info FROM lorem", (err, row) => {
        console.log(row.id + ": " + row.info);
    });
});

db.close();

您的测试可能需要另一个任务来在测试流程中的某些点创建/更新/删除数据库记录。您应该能够调整上面的代码来处理这个问题。


1
投票

我正在尝试在我的 C# 应用程序上实现内存中的 Sqlite 数据库以用于测试目的。

由于目标是使用应用程序进行单元测试,因此要使用

HasData
方法,您将需要创建一个从应用程序上下文继承的类(或者您将在实际上下文中拥有种子数据)。

此外,

HasData
是一种更有限的方法,因为数据被应用于测试的所有上下文实例。这是有道理的,但有一些共享数据可用于所有情况,但我个人倾向于通过某种共享方法引入此类数据(这将执行
AddRange
SaveChanges
),这在某种 中被称为一次性设置(取决于所使用的测试框架),这是一种更灵活的方法,并且允许对所需进行更精细的控制。

我还建议研究一件事 - 使用 testcontainers 进行此类测试而不是内存中的 SQLite,即启动数据库容器根据需要进行设置并使用它,这将通过使用产生更相关的测试结果特定的数据库服务器。


0
投票

我最终选择了每次运行测试时在 Docker 容器上启动的 SQL Server DB 映像,因为 SQLite 和 Sql Server 之间存在无法克服的差异,并且它们会干扰测试。 但是如果有人想要填充 Sqlite 数据库进行测试,您可以将类似的内容添加到

Configure()
中的
Startup
方法中:

context.Database.EnsureCreated();
//call service to populate database
SqliteDbSeeder.PopulateDatabase(context);

SqliteDbSeeder.PopulateDatabase()
方法使用
context.AddRange()
SaveChanges()
将实体添加到数据库中。我实际上将它们保存在 json 文件中,将它们转换为实体,然后将它们添加到数据库中。

© www.soinside.com 2019 - 2024. All rights reserved.