eve*_*ert 4 c# sqlite unit-testing entity-framework asp.net-core
我有一个使用 .NET Framework 4.6.1 和 EF6 的 ASP.NET Core 项目。现在我想编写一些单元测试,并且已经花了几个小时来配置内存 SQLite 数据库以使用 EF6。但这不起作用。
那么,问题是如何在没有任何模拟(而不是内存数据库)的情况下使用 EF6 测试我的项目?
我当前的代码:
public class DataAccessLayer : DbContext
{
public DataAccessLayer(string connectionString)
: base(connectionString) {
}
public DataAccessLayer(DbConnection connection)
: base(connection, true) {
}
public DbSet<User> Users { get; set; }
public DbSet<Setting> Settings { get; set; }
public DbSet<UserRole> UserRoles { get; set; }
public DbSet<MainKey> MainKeys { get; set; }
}
[Table("Users")]
public class User
{
[Key]
[Required]
public int UserID { get; set; }
[Required][StringLength(50)]
public string UserName { get; set; }
...
}
public class Testbase
{
protected DataAccessLayer Context { get; private set; }
[TestInitialize]
public virtual void SetUp()
{
var connection = this.CreateConnection();
connection.Open();
this.Context = new DataAccessLayer(connection);
this.Context.Database.CreateIfNotExists();
}
private SQLiteConnection CreateConnection() {
var connectionStringBuilder = new SQLiteConnectionStringBuilder { DataSource = ":memory:" };
return new SQLiteConnection(connectionStringBuilder.ToString());
}
}
Run Code Online (Sandbox Code Playgroud)
如果我尝试添加用户,则会收到以下错误:
System.Data.SQLite.SQLiteException:SQL逻辑错误或丢失数据库没有这样的表:用户。
我假设我的表是通过调用生成的this.Context.Database.CreateIfNotExists();,还是我弄错了?
考虑使用 Nuget 包Effort
它是一个简单且快速的内存数据库,用于单元测试。
您可以从一个空数据库启动并使用数据库播种器自行填充,也可以使用测试 CSV 文件中的值填充它。
包含博客和帖子的数据库的简单示例。博客和帖子之间的一对多关系
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public virtual Blog Blog { get; set; }
}
public class BloggingContext : DbContext
{
public BloggingContext() : base() { } // constructor using config file
public BloggingContext(string nameOrConnectionString) : base(nameOrConnectionString) { }
public BloggingContext(DbConnection connection) : base(connection, true) { }
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
您不会获得数据库的连接字符串,而是获得数据库的 DbConnection。因此是 BloggingContext 的第三个构造函数。
在此构造函数中传递给超类的布尔值是为了告诉 DbContext 它拥有该连接:当连接被处置时,DbContext 应该关闭并处置该连接。
这是与正常 DbContext 使用的唯一区别。对 DbContext 和 DbSets 的所有其他调用都正常。
例子
static void Main(string[] args)
{
var connection = Effort.DbConnectionFactory.CreateTransient();
using (var dbContext = new BloggingContext(connection))
{
var addedBlog = dbContext.Blogs.Add(new Blog[]
{
Name = "1",
Posts = new Post[]
{
new Post() {Title = "1st", Content = "a"},
new Post() {Title = "2nd", Content = "b"},
new Post() {Title = "3rd", Content = "c"},
},
});
dbContext.SaveChanges();
}
using (var dbContext = new BloggingContext(connection))
{
var allPosts = dbContext.Posts.ToList();
foreach (var post in allPosts)
{
Console.WriteLine($"{post.Id}: {post.Title}");
}
}
Run Code Online (Sandbox Code Playgroud)
提示:在开发过程中,有时很难看出测试失败是因为测试(数据)不正确还是因为测试的代码不正确。在调试期间检查测试期间数据库中的内容相当困难。因此,我倾向于使用充满测试值的真实数据库来开发测试,一旦很少需要调试测试,就切换到内存数据库。事实上,对我来说,这是第二个或第三个 DbContext 构造函数之间的切换
| 归档时间: |
|
| 查看次数: |
4463 次 |
| 最近记录: |