将起订量与 Entity Framework 一起使用 6 - 模拟包含和位置
Using Moq with Entity Framework 6 - Mocking Include and Where
我正在尝试使用 Moq 和 EntityFramework.Testing.Moq
扩展方法创建一些内存中 dbContext
模拟:
https://github.com/scott-xu/EntityFramework.Testing
当我尝试使用模拟上下文对急切加载的查询进行单元测试时,我遇到了困难。问题是,根本没有选择任何东西。我知道应该选择一些东西,因为当我使用 LINQPad 将同一个查询指向我的源数据库时,我得到了我期望的 2 个结果。
我永远不知道我需要多少代码等post,所以希望下面的内容会有所帮助。
数据图
我有两个主表,dbo.Applicant
主要包含用户详细信息,dbo.Application
包含求职申请,dbo.Application
挂钩了查找表:
示例模型
这是基于上图的代码优先方法。我已删除属性以保持代码干净并切合问题的要点:
[Table("Application")]
public partial class Application
{
[Min(1)]
public int Id { get; set; }
[Required]
[StringLength(50)]
public string ApplicationId { get; set; }
[Min(1)]
public int ApplicantId { get; set; }
public virtual Applicant Applicant { get; set; }
}
[Table("Applicant")]
public partial class Applicant
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Applicant()
{
Applications = new HashSet<Application>();
RowStatus = "L";
}
public int Id { get; set; }
[Required]
public string FullName { get; set; }
[Required]
public string AddressLine1 { get; set; }
[Required]
public string Email { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Application> Applications { get; set; }
}
上下文
再次减少上下文,但以防万一我在评论中要求它:
public partial class WorkExperienceContext : DbContext
{
public WorkExperienceContext()
: base("name=WorkExperienceContext")
{
this.Configuration.LazyLoadingEnabled = false;
}
public WorkExperienceContext(string userTestConnectionString)
: base(userTestConnectionString)
{
Trace.Write("Using test context " + Add to dictionary);
}
public virtual DbSet<Applicant> Applicants { get; set; }
public virtual DbSet<Application> Applications { get; set; }
}
单元测试方法
以下是(再次)单元测试方法的精简版,我希望两个应用程序记录可以通过基于电子邮件。
从下面可以看出,有:
- 2
Application
条路西法记录 (ApplicantId = 666)
- 有一条
Applicant
条记录,其电子邮件为 misunderstood@fireandbrimestone.co.uk
我的问题是 test
是 null
,当使用相同的代码查询数据库本身时,我得到了正确的结果。我很困惑我需要做什么。请记住,我正在使用 EntityFramework.Testing.Moq.SetupData()
方法来处理 DbSet
方法的模拟并将 List<>
种子数据转换为 IQueryable
集合。
public void InMemory_Find_Application_By_Email_EFMoq()
{
var applications = new List<Application>
{
new Application { Id = 1, ApplicantId = 666, ApplicationId = "1-a", DivisionId = 2, PublishingAreaId = 4, SourceId = 2, SkillsLearnt = "How to pick up pen", RowStatus="L", ApplicantStartDateId = 1,
ApplicantDisabilityId = 2, CreatedDate = DateTime.Now, CreatedTime = DateTime.Now.TimeOfDay } ,
new Application { Id = 2, ApplicantId = 666, ApplicationId = "1-a", DivisionId = 3, PublishingAreaId = 4, SourceId = 2, SkillsLearnt = "How to pick up pen", RowStatus="L", ApplicantStartDateId = 1,
ApplicantDisabilityId = 2,CreatedDate = DateTime.Now, CreatedTime = DateTime.Now.TimeOfDay } ,
new Application { Id = 3, ApplicantId = 5, ApplicationId = "1-b", DivisionId = 3, PublishingAreaId = 1, SourceId = 2, SkillsLearnt = "Reading a book well" , RowStatus="L", ApplicantStartDateId = 1,
ApplicantDisabilityId = 2,CreatedDate = DateTime.Now, CreatedTime = DateTime.Now.TimeOfDay } ,
new Application { Id = 4, ApplicantId = 5, ApplicationId = "1-b", DivisionId = 2, PublishingAreaId = 1, SourceId = 2, SkillsLearnt = "Reading a book well ", RowStatus="L", ApplicantStartDateId = 1,
ApplicantDisabilityId = 2 ,CreatedDate = DateTime.Now, CreatedTime = DateTime.Now.TimeOfDay } ,
new Application { Id = 5, ApplicantId = 5, ApplicationId = "1-b", DivisionId = 7, PublishingAreaId = 1, SourceId = 2, SkillsLearnt = "Reading a book well" , RowStatus="L", ApplicantStartDateId = 1,
ApplicantDisabilityId = 2 ,CreatedDate = DateTime.Now, CreatedTime = DateTime.Now.TimeOfDay } ,
new Application { Id = 6, ApplicantId = 24, ApplicationId = "1-c", DivisionId = 10, PublishingAreaId = 3, SourceId = 1, SkillsLearnt = "I can now re-iterate stuff", RowStatus="L", ApplicantStartDateId = 1,
ApplicantDisabilityId = 2,CreatedDate = DateTime.Now, CreatedTime = DateTime.Now.TimeOfDay },
new Application { Id = 7, ApplicantId = 21, ApplicationId = "1-d", DivisionId = 2, PublishingAreaId = 2, SourceId = 1, SkillsLearnt = "I made some bread the other day", RowStatus="L", ApplicantStartDateId = 1,
ApplicantDisabilityId = 2 ,CreatedDate = DateTime.Now, CreatedTime = DateTime.Now.TimeOfDay }
};
var applicants = new List<Applicant>
{
new Applicant {Id = 5, FullName = "Pen Is", AddressLine1="Somewhere Over the Rainbow", County="West Sussex", Email="pen_is@hotmail.co.uk", RowStatus = "L",
GenderId = 2, EducationId = 1, CreatedDate = DateTime.Now, CreatedTime = DateTime.Now.TimeOfDay, PostCode="PEN 1ST", Telephone="N/A"},
new Applicant {Id = 24, FullName = "Gareth Bradley", AddressLine1="an address", County="West Sussex", Email="gareth.bradley@hachette.co.uk", RowStatus = "L",
GenderId = 2, EducationId = 1, CreatedDate = DateTime.Now, CreatedTime = DateTime.Now.TimeOfDay, PostCode="bn13 3qb",Telephone="N/A"} ,
new Applicant {Id = 21, FullName = "Lizzy Windsor", AddressLine1="A Palace (Take your pick)", County="Berkshire", Email="HerRoyalMaj@TheCrownJewels.co.uk", RowStatus = "L",
GenderId = 2, EducationId = 1, CreatedDate = DateTime.Now, CreatedTime = DateTime.Now.TimeOfDay, PostCode="BE1 1HM",Telephone="N/A"} ,
new Applicant {Id = 666, FullName = "Lucifer MorningStar", AddressLine1="Hotsy Street", County="Down South", Email="misunderstood@fireandbrimes1one.co.uk" , RowStatus = "L",
GenderId = 3, EducationId = 1, CreatedDate = DateTime.Now, CreatedTime = DateTime.Now.TimeOfDay, PostCode="HE11 6SS",Telephone="666-666"}
};
foreach (Applicant applicant in applicants)
{
applicant.Applications = applications.Where(a => a.ApplicantId == applicant.Id).ToArray();
}
foreach (Application application in applications)
{
application.Applicant = applicants.SingleOrDefault(a => a.Id == application.ApplicantId);
}
var mockSet = new Mock<DbSet<Application>>()
.SetupData(applications);
var mockSetUsers = new Mock<DbSet<Applicant>>()
.SetupData(applicants);
var mockContext = new Mock<WorkExperienceContext>();
mockContext.Setup(c => c.Applications).Returns(mockSet.Object);
mockContext.Setup(c => c.Applicants).Returns(mockSetUsers.Object);
var mockService = new WorkExperienceFormService(mockContext.Object);
var test = mockContext.Object
.Applications
.Include(a => a.Applicant)
.Where(e => e.Applicant.Email == "misunderstood@fireandbrimestone.co.uk")
.ToList();
Assert.AreEqual(2, test.Count());
}
以下是我的 LINQPad 在没有模拟上下文的情况下提取数据的证据:
可能是您发布代码时的错字,但是 e-mail 对应 'Lucifer MorningStar' 是
misunderstood@fireandbrimes1one.co.uk 而不是
misunderstood@fireandbrimestone.co.uk
我正在尝试使用 Moq 和 EntityFramework.Testing.Moq
扩展方法创建一些内存中 dbContext
模拟:
https://github.com/scott-xu/EntityFramework.Testing
当我尝试使用模拟上下文对急切加载的查询进行单元测试时,我遇到了困难。问题是,根本没有选择任何东西。我知道应该选择一些东西,因为当我使用 LINQPad 将同一个查询指向我的源数据库时,我得到了我期望的 2 个结果。
我永远不知道我需要多少代码等post,所以希望下面的内容会有所帮助。
数据图
我有两个主表,dbo.Applicant
主要包含用户详细信息,dbo.Application
包含求职申请,dbo.Application
挂钩了查找表:
示例模型
这是基于上图的代码优先方法。我已删除属性以保持代码干净并切合问题的要点:
[Table("Application")]
public partial class Application
{
[Min(1)]
public int Id { get; set; }
[Required]
[StringLength(50)]
public string ApplicationId { get; set; }
[Min(1)]
public int ApplicantId { get; set; }
public virtual Applicant Applicant { get; set; }
}
[Table("Applicant")]
public partial class Applicant
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Applicant()
{
Applications = new HashSet<Application>();
RowStatus = "L";
}
public int Id { get; set; }
[Required]
public string FullName { get; set; }
[Required]
public string AddressLine1 { get; set; }
[Required]
public string Email { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Application> Applications { get; set; }
}
上下文
再次减少上下文,但以防万一我在评论中要求它:
public partial class WorkExperienceContext : DbContext
{
public WorkExperienceContext()
: base("name=WorkExperienceContext")
{
this.Configuration.LazyLoadingEnabled = false;
}
public WorkExperienceContext(string userTestConnectionString)
: base(userTestConnectionString)
{
Trace.Write("Using test context " + Add to dictionary);
}
public virtual DbSet<Applicant> Applicants { get; set; }
public virtual DbSet<Application> Applications { get; set; }
}
单元测试方法
以下是(再次)单元测试方法的精简版,我希望两个应用程序记录可以通过基于电子邮件。
从下面可以看出,有:
- 2
Application
条路西法记录 (ApplicantId = 666) - 有一条
Applicant
条记录,其电子邮件为 misunderstood@fireandbrimestone.co.uk
我的问题是 test
是 null
,当使用相同的代码查询数据库本身时,我得到了正确的结果。我很困惑我需要做什么。请记住,我正在使用 EntityFramework.Testing.Moq.SetupData()
方法来处理 DbSet
方法的模拟并将 List<>
种子数据转换为 IQueryable
集合。
public void InMemory_Find_Application_By_Email_EFMoq()
{
var applications = new List<Application>
{
new Application { Id = 1, ApplicantId = 666, ApplicationId = "1-a", DivisionId = 2, PublishingAreaId = 4, SourceId = 2, SkillsLearnt = "How to pick up pen", RowStatus="L", ApplicantStartDateId = 1,
ApplicantDisabilityId = 2, CreatedDate = DateTime.Now, CreatedTime = DateTime.Now.TimeOfDay } ,
new Application { Id = 2, ApplicantId = 666, ApplicationId = "1-a", DivisionId = 3, PublishingAreaId = 4, SourceId = 2, SkillsLearnt = "How to pick up pen", RowStatus="L", ApplicantStartDateId = 1,
ApplicantDisabilityId = 2,CreatedDate = DateTime.Now, CreatedTime = DateTime.Now.TimeOfDay } ,
new Application { Id = 3, ApplicantId = 5, ApplicationId = "1-b", DivisionId = 3, PublishingAreaId = 1, SourceId = 2, SkillsLearnt = "Reading a book well" , RowStatus="L", ApplicantStartDateId = 1,
ApplicantDisabilityId = 2,CreatedDate = DateTime.Now, CreatedTime = DateTime.Now.TimeOfDay } ,
new Application { Id = 4, ApplicantId = 5, ApplicationId = "1-b", DivisionId = 2, PublishingAreaId = 1, SourceId = 2, SkillsLearnt = "Reading a book well ", RowStatus="L", ApplicantStartDateId = 1,
ApplicantDisabilityId = 2 ,CreatedDate = DateTime.Now, CreatedTime = DateTime.Now.TimeOfDay } ,
new Application { Id = 5, ApplicantId = 5, ApplicationId = "1-b", DivisionId = 7, PublishingAreaId = 1, SourceId = 2, SkillsLearnt = "Reading a book well" , RowStatus="L", ApplicantStartDateId = 1,
ApplicantDisabilityId = 2 ,CreatedDate = DateTime.Now, CreatedTime = DateTime.Now.TimeOfDay } ,
new Application { Id = 6, ApplicantId = 24, ApplicationId = "1-c", DivisionId = 10, PublishingAreaId = 3, SourceId = 1, SkillsLearnt = "I can now re-iterate stuff", RowStatus="L", ApplicantStartDateId = 1,
ApplicantDisabilityId = 2,CreatedDate = DateTime.Now, CreatedTime = DateTime.Now.TimeOfDay },
new Application { Id = 7, ApplicantId = 21, ApplicationId = "1-d", DivisionId = 2, PublishingAreaId = 2, SourceId = 1, SkillsLearnt = "I made some bread the other day", RowStatus="L", ApplicantStartDateId = 1,
ApplicantDisabilityId = 2 ,CreatedDate = DateTime.Now, CreatedTime = DateTime.Now.TimeOfDay }
};
var applicants = new List<Applicant>
{
new Applicant {Id = 5, FullName = "Pen Is", AddressLine1="Somewhere Over the Rainbow", County="West Sussex", Email="pen_is@hotmail.co.uk", RowStatus = "L",
GenderId = 2, EducationId = 1, CreatedDate = DateTime.Now, CreatedTime = DateTime.Now.TimeOfDay, PostCode="PEN 1ST", Telephone="N/A"},
new Applicant {Id = 24, FullName = "Gareth Bradley", AddressLine1="an address", County="West Sussex", Email="gareth.bradley@hachette.co.uk", RowStatus = "L",
GenderId = 2, EducationId = 1, CreatedDate = DateTime.Now, CreatedTime = DateTime.Now.TimeOfDay, PostCode="bn13 3qb",Telephone="N/A"} ,
new Applicant {Id = 21, FullName = "Lizzy Windsor", AddressLine1="A Palace (Take your pick)", County="Berkshire", Email="HerRoyalMaj@TheCrownJewels.co.uk", RowStatus = "L",
GenderId = 2, EducationId = 1, CreatedDate = DateTime.Now, CreatedTime = DateTime.Now.TimeOfDay, PostCode="BE1 1HM",Telephone="N/A"} ,
new Applicant {Id = 666, FullName = "Lucifer MorningStar", AddressLine1="Hotsy Street", County="Down South", Email="misunderstood@fireandbrimes1one.co.uk" , RowStatus = "L",
GenderId = 3, EducationId = 1, CreatedDate = DateTime.Now, CreatedTime = DateTime.Now.TimeOfDay, PostCode="HE11 6SS",Telephone="666-666"}
};
foreach (Applicant applicant in applicants)
{
applicant.Applications = applications.Where(a => a.ApplicantId == applicant.Id).ToArray();
}
foreach (Application application in applications)
{
application.Applicant = applicants.SingleOrDefault(a => a.Id == application.ApplicantId);
}
var mockSet = new Mock<DbSet<Application>>()
.SetupData(applications);
var mockSetUsers = new Mock<DbSet<Applicant>>()
.SetupData(applicants);
var mockContext = new Mock<WorkExperienceContext>();
mockContext.Setup(c => c.Applications).Returns(mockSet.Object);
mockContext.Setup(c => c.Applicants).Returns(mockSetUsers.Object);
var mockService = new WorkExperienceFormService(mockContext.Object);
var test = mockContext.Object
.Applications
.Include(a => a.Applicant)
.Where(e => e.Applicant.Email == "misunderstood@fireandbrimestone.co.uk")
.ToList();
Assert.AreEqual(2, test.Count());
}
以下是我的 LINQPad 在没有模拟上下文的情况下提取数据的证据:
可能是您发布代码时的错字,但是 e-mail 对应 'Lucifer MorningStar' 是 misunderstood@fireandbrimes1one.co.uk 而不是 misunderstood@fireandbrimestone.co.uk