我知道还有其他帖子也有类似的问题,但我找不到具体的答案,所以我在这里:D。我正在为我正在构建的 Dapper API 创建单元测试。该 API 是用 C# 构建的,并连接到生产中的 Postgres DB。 API 使用 DI 和 IDbConnectionFactory 向控制器提供连接字符串。为了测试 API,我创建了一个 MStest 项目来测试控制器。我一直在尝试在内存数据库中创建一个 sqlite 来模拟实际的数据库,以免依赖于外部依赖项,即我的 Postgres 数据库。
我已经成功地创建了数据库并用数据填充它,并验证了其中包含示例数据。但是当尝试将此 sqlite 连接字符串传递到我的控制器时,它说找不到表......请帮助:D
//my controller
using CrudApi.Models;
using CrudApi.DbConnectionFactories;
using Dapper;
using Microsoft.AspNetCore.Mvc;
using Npgsql;
using System.Data.Common;
namespace CrudApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class HolidayController : ControllerBase
{
// Api Boiler Plate
private readonly IConfiguration config;
private readonly DbConnection _connection;
public HolidayController(IConfiguration config, IDbConnectionFactory connectionFactory)
{
this.config = config;
_connection = connectionFactory.CreateConnection();
}
// Gets all the Holiday in the DB
[HttpGet]
public async Task<ActionResult<List<Holiday>>> GetAllHoliday()
{
IEnumerable<Holiday> holiday = await SelectAllHoliday(_connection);
return Ok(holiday);
}
private static async Task<IEnumerable<Holiday>> SelectAllHoliday(DbConnection connection)
{
return await connection.QueryAsync<Holiday>("select * from tbl03_holiday;");
}
}
}
//test for controller
using CrudApi.Controllers;
using CrudApi.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.Sqlite;
using Microsoft.Extensions.Configuration;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Data;
using System.Threading.Tasks;
using System.Data.Common;
using System;
namespace CrudApi.Tests
{
[TestClass]
public class HolidayControllerTests
{
private static IConfiguration _config;
private static DbConnection _connection; // Change the type to DbConnection
private static HolidayController _controller;
[ClassInitialize]
public static void ClassInitialize(TestContext context)
{
var configBuilder = new ConfigurationBuilder();
_config = configBuilder.Build();
// Create an in-memory SQLite database connection factory
var connectionFactory = new SqliteConnectionFactory("DataSource=:memory:;Cache=Shared");
_connection = connectionFactory.CreateConnection();
_connection.Open(); // Keep the connection open for the duration of the tests
// Create the controller
_controller = new HolidayController(_config, connectionFactory);
// Initialize the database schema and populate with test data
InitializeDatabase(_connection);
}
[ClassCleanup]
public static void ClassCleanup()
{
// Cleanup resources
if (_connection != null)
{
_connection.Close();
}
}
private static void InitializeDatabase(DbConnection connection)
{
if (connection.State == ConnectionState.Open)
{
Console.WriteLine("connection is open");
}
else
{
Console.WriteLine("connection is closed");
}
connection.Open(); // Open the connection
using (var command = connection.CreateCommand())
{
command.CommandText = @"
CREATE TABLE tbl03_holiday (
holiday_id INTEGER PRIMARY KEY AUTOINCREMENT,
uid TEXT NOT NULL,
from_date TEXT NOT NULL,
to_date TEXT NOT NULL,
holiday_type TEXT NOT NULL
);
INSERT INTO tbl03_holiday (holiday_id, uid, from_date, to_date, holiday_type) VALUES (1, 'test1', '0001-01-01', '00001-01-02', 'Holiday 1');
INSERT INTO tbl03_holiday (holiday_id, uid, from_date, to_date, holiday_type) VALUES (2, 'test2', '0001-01-01', '00001-01-02', 'Holiday 2');
";
command.CommandType = CommandType.Text;
command.ExecuteNonQuery();
Console.WriteLine("Table created");
}
}
private static void DisplayTableData(string tableName, DbConnection connection)
{
using (var command = connection.CreateCommand())
{
command.CommandText = $"SELECT * FROM {tableName};";
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
for (int i = 0; i < reader.FieldCount; i++)
{
Console.Write($"{reader.GetName(i)}: {reader.GetValue(i)}\t");
}
Console.WriteLine();
}
}
}
}
[TestMethod]
public void TestDisplayTableData()
{
DisplayTableData("tbl03_holiday", _connection);
}
[TestMethod]
public async Task GetAllHoliday_Returns_All_Holidays()
{
// Arrange
if (_connection.State == ConnectionState.Open)
{
Console.WriteLine("Connection is open");
}
else
{
Console.WriteLine("Connection is closed");
}
//Print the connection string
var connectionString = _connection.ConnectionString;
Console.WriteLine($"Test method called with connection string: {connectionString}");
// Act
var result = await _controller.GetAllHoliday();
// Assert
Assert.IsNotNull(result);
Assert.IsInstanceOfType(result.Result, typeof(OkObjectResult));
var okResult = result.Result as OkObjectResult;
Assert.IsInstanceOfType(okResult.Value, typeof(List<Holiday>));
var holidays = okResult.Value as List<Holiday>;
Assert.AreEqual(2, holidays.Count);
}
}
}
My current output:
Passed TestDisplayTableData [3 ms]
Standard Output Messages:
connection is open
Table created
holiday_id: 1 uid: test1 from_date: 0001-01-01 to_date: 00001-01-02 holiday_type: Holiday 1
holiday_id: 2 uid: test2 from_date: 0001-01-01 to_date: 00001-01-02 holiday_type: Holiday 2
Failed GetAllHoliday_Returns_All_Holidays [122 ms]
Error Message:
Test method CrudApi.Tests.HolidayControllerTests.GetAllHoliday_Returns_All_Holidays threw exception:
Microsoft.Data.Sqlite.SqliteException: SQLite Error 1: 'no such table: tbl03_holiday'.
Stack Trace:
at Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(Int32 rc, sqlite3 db)
at Microsoft.Data.Sqlite.SqliteCommand.PrepareAndEnumerateStatements()+MoveNext()
at Microsoft.Data.Sqlite.SqliteCommand.GetStatements()+MoveNext()
at Microsoft.Data.Sqlite.SqliteDataReader.NextResult()
at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior behavior)
at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)
at Microsoft.Data.Sqlite.SqliteCommand.ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)
at Dapper.SqlMapper.QueryAsync[T](IDbConnection cnn, Type effectiveType, CommandDefinition command) in /_/Dapper/SqlMapper.Async.cs:line 434
at CrudApi.Controllers.HolidayController.SelectAllHoliday(DbConnection connection) in
Standard Output Messages:
Connection is open
Test method called with connection string: DataSource=:memory:;Cache=Shared
如果我没有提供足够的信息,请随时说
根据 Microsoft:
使用特殊的数据源文件名:内存:创建内存中 数据库。当连接关闭时,数据库将被删除。 什么时候 使用:内存:,每个连接创建自己的数据库。
链接页面建议为持久内存数据库使用不同的连接字符串格式:
Data Source=InMemorySample;Mode=Memory;Cache=Shared