今天的主题是要针对开发 .NET 应用程序最常遇到的资料库处理(参考文章:Easily Perform LINQ Mocking to Unit Test ASP.NET Core Application),而资料库处理手法有数种方式如原生 SQL、Entity Framework、Dapper 等手法;其中,我们以 Entity Framework 为本次的范例,再讨论 Entity Framework 之前,要先了解 C# 很常用的资料处理语法 —— LINQ。
LINQ 是一套可做为 .NET 开发环境中 C# 资料物件的查询、传递、转换的语法框架,也就是在 .NET 环境中可以用 SQL 的逻辑对资料进行处理;举例来说,若没有 LINQ 语法之前,假设现在有一组 C# 物件要取出符合条件的资料,程序码如下:
class Program
{
static void Main()
{
List<string> classmates = new List<string> { "David", "Mary", "Mandy", "Kevin" };
List<string> classmatesMStart = new List<string>();
foreach (string classmate in classmates)
{
if (classmate[0].Equals("M"))
{
classmatesMStart.Add(classmate);
}
}
foreach (string classmate in classmates)
{
Console.WriteLine(classmate);
}
}
}
但如果今天是用 LINQ 语法,则程序码如下:
class Program
{
static void Main()
{
List<string> classmates = new List<string> { "David", "Mary", "Mandy", "Kevin" };
List<string> classmateMStart = classmates.Where(c => c[0].Equals("M")).ToList();
foreach (string classmate in classmates)
{
Console.WriteLine(classmate);
}
}
}
所以实务上还满常使用 LINQ,那接下来概述 Entity Framework 的功能。
Entity Framework 是应用於 .NET 与 SQL 之间沟通的桥梁,采用 (ORM, Object Relational Mapping) 技术,使用 Entity Framework 的好处是像资料库连线、关闭等等都已经处理好,只需专注在商业逻辑的撰写上即可。其中,使用 Entity Framework 会自动产制类似如下的程序码,这部分主要是跟 SQL 资料表之间的联系;同时,也是我们单元测试主要的测试目标,若想了解更细的内容,可参考 Entity Framework Tutorial。
public partial class ClassmateContext : DbContext
{
public ClassmateContext()
{
}
public ClassmateContext(DbContextOptions<ClassmateContext> options)
: base(options)
{
}
public virtual DbSet<Classmate> Classmates { get; set; }
// ...
}
图一、Entity Framework 框架图(图源:Entity Framework Tutorial)
因此,今天的主题就在於如何在使用 Entity Framework 的情境下,做测试时把 Entity Framework 相关的元件抽离并注入假物件,并且假物件需符合 LINQ 可使用的格式,那我们先来看商业逻辑的部分:
public class ClassmateClass {
private ClassmateContext ct;
public ClassmateClass(ClassmateContext inCt) {
ct = inCt;
}
public int GetClassmateId(string classmateName)
{
int classmateId = 0;
if (!string.IsNullOrEmpty(classmateName))
{
classmateId = ct.Classmates
.Where(d => d.Name.Equals(classmateName))
.Select(d => d.Id)
.FirstOrDefault();
}
return classmateId;
}
}
在从商业逻辑中,我们可以看到 Id 主要是从 Context 中的 Classmate Dbset 取得相对应的资料;因此,接下来要做的事情就是把 ClassmateContext 抽换成虚设常式,程序码如下:
public class StubClassmateContext<T>
{
public ClassmateContext GetClassmateContext()
{
var options = new DbContextOptionsBuilder<ClassmateContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
var context = new ClassmateContext(options);
context.Classmates.Add(new Classmate { Id = 100, Name = "Kevin" });
context.SaveChanges();
return context;
}
}
因此,就可以透过建构函式把虚设常式注入,如下:
[Test]
public void DemoStubContextTest()
{
// Arrange
var stubCt = new StubClassmateContext<ClassmateContext>().GetClassmateContext();
var classmateClass = new ClassmateClass(stubCt);
// Act
int classmateId = classmateClass.GetClassmateId("Kevin");
// Assert
Assert.AreEqual(100, classmateId);
}
这样就算是把 Entity Framework 连线至真实的资料库抽换成自己设定的假资料,虽然在建立 StubClassmateContext 时所建立的连线依旧有用 Entity Framework 的语法(换言之,已经并非达到百分百自己控制的测试码);但以能验证从 Entity Framework 取出来的资料所做的逻辑是否正确,还是有其效益。
<<: Swift纯Code之旅 Day14. 「TableView(5) - 点击TableViewCell」
>>: 2.3 Design System - Design Token
本篇文章同步发表在 HKT 线上教室 部落格,线上影音教学课程已上架至 Udemy 和 Youtu...
我们常常听到,在一个ML专案当中,会需要做各种的资料监控。这些资料监控包含哪些呢? 开发流程 在开发...
接着针对资料型态为数字进行说明: Bool 资料型态为: True 与 False 使用 bool(...
LINE Developers:https://developers.line.biz/zh-ha...
此系列文章会同步发文到个人部落格,有兴趣的读者可以前往观看喔。 今天要跟大家分享当网页上有子表时,...