C# 先在EF6DB中模拟数据库
我很难弄清楚如何模拟我的数据库来对我的WebAPI控制器进行单元测试。我找到的所有资源都适用于代码优先EF,但不适用于自动生成上下文的db优先 简单地说,我希望能够调用我的控制器的CRUD操作来对抗我在运行中创建的假数据库,我正在寻找最直接的方法来实现这一点 我试图用它把它放在一起,但无法管理 我的上下文定义为:C# 先在EF6DB中模拟数据库,c#,entity-framework,unit-testing,testing,ef-database-first,C#,Entity Framework,Unit Testing,Testing,Ef Database First,我很难弄清楚如何模拟我的数据库来对我的WebAPI控制器进行单元测试。我找到的所有资源都适用于代码优先EF,但不适用于自动生成上下文的db优先 简单地说,我希望能够调用我的控制器的CRUD操作来对抗我在运行中创建的假数据库,我正在寻找最直接的方法来实现这一点 我试图用它把它放在一起,但无法管理 我的上下文定义为: public partial class MyEntities : DbContext { public MyEntities() : base("name=M
public partial class MyEntities : DbContext
{
public MyEntities()
: base("name=MyEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Company> Companies { get; set; }
公共部分类myenties:DbContext
{
公共慈善机构()
:base(“name=MyEntities”)
{
}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
抛出新代码FirstException();
}
公共虚拟数据库集公司{get;set;}
现在我明白了,我需要创建一个IContext,允许对MyEntities进行模拟,但我不知道如何组织它
我尝试过添加以下类,但不知道如何组织这些类
public interface IContext
{
IObjectSet<Company> Companies { get; }
void SaveChanges();
}
public class EFContext: IContext
{
private readonly MyEntities _data;
public EFContext()
{
_data = new MyEntities();
}
public IObjectSet<Company> Companies
{
get
{
return _data.CreateObjectSet<Company>();
}
}
public void SaveChanges()
{
_data.SaveChanges();
}
}
公共接口IContext
{
IObjectSet公司{get;}
void SaveChanges();
}
公共类EFContext:IContext
{
私有只读MyEntities_数据;
公共环境()
{
_数据=新的MyEntities();
}
公共对象集公司
{
得到
{
返回_data.CreateObjectSet();
}
}
公共void SaveChanges()
{
_data.SaveChanges();
}
}
示例
我想对示例控制器进行单元测试,如果我可以模拟一个数据库进行测试,这将非常容易
public IHttpActionResult Search([FromBody]string query)
{
var companies = CompanyRepository.Get().Where(c => c.Name.ToLower().Contains(query.ToLower()));
var people = PersonRepository.Get().Where(c => c.FirstName.ToLower().Contains(query.ToLower()) || c.LastName.ToLower().Contains(query.ToLower()));
List<SearchResult> results = new List<SearchResult>();
foreach(Company company in companies)
results.Add(new SearchResult { ID = company.ID, Name = company.Name, Type = "Company" });
foreach (Person person in people)
results.Add(new SearchResult { ID = person.ID, Name = person.FirstName + " " + person.LastName, Type = "Person" });
return Ok(results);
}
公共IHttpActionResult搜索([FromBody]字符串查询)
{
var companys=CompanyRepository.Get(),其中(c=>c.Name.ToLower().Contains(query.ToLower());
var people=PersonRepository.Get().Where(c=>c.FirstName.ToLower().Contains(query.ToLower())| | c.LastName.ToLower().Contains(query.ToLower());
列表结果=新列表();
foreach(公司中的公司)
添加(新的搜索结果{ID=company.ID,Name=company.Name,Type=“company”});
foreach(人对人)
添加(新的搜索结果{ID=person.ID,Name=person.FirstName+“”+person.LastName,Type=“person”});
返回Ok(结果);
}
于2015年7月11日更新 因此,我可以看到一些测试:
public class MyController : ApiController
{
private ICompanyRepository companyRepository;
private IPersonRepository personRepository;
public MyController ()
{
companyRepository = new CompanyRepository();
personRepository = new PersonRepository();
}
public MyController (ICompanyRepository CompanyRepository, IPersonRepository PersonRepository )
{
companyRepository = CompanyRepository;
personRepository = PersonRepository;
}
}
然后,您的代码需要引用私有存储库
public IHttpActionResult Search([FromBody]string query)
{
var companies = companyRepository.Get().Where(c => c.Name.ToLower().Contains(query.ToLower()));
var people = personRepository.Get().Where(c => c.FirstName.ToLower().Contains(query.ToLower()) || c.LastName.ToLower().Contains(query.ToLower()));
List<SearchResult> results = new List<SearchResult>();
foreach(Company company in companies)
results.Add(new SearchResult { ID = company.ID, Name = company.Name, Type = "Company" });
foreach (Person person in people)
results.Add(new SearchResult { ID = person.ID, Name = person.FirstName + " " + person.LastName, Type = "Person" });
return Ok(results);
}
公共IHttpActionResult搜索([FromBody]字符串查询)
{
var companys=companyRepository.Get(),其中(c=>c.Name.ToLower().Contains(query.ToLower());
var people=personRepository.Get().Where(c=>c.FirstName.ToLower().Contains(query.ToLower())| | c.LastName.ToLower().Contains(query.ToLower());
列表结果=新列表();
foreach(公司中的公司)
添加(新的搜索结果{ID=company.ID,Name=company.Name,Type=“company”});
foreach(人对人)
添加(新的搜索结果{ID=person.ID,Name=person.FirstName+“”+person.LastName,Type=“person”});
返回Ok(结果);
}
然后,您的测试看起来像(取决于您使用的测试和模拟框架)。请注意,这是相当粗糙的编码,如果粘贴,将无法工作!:
[TestClass]
public class MyControllerTests
{
Mock<ICompanyRepository>() mockCompanyRepository = new Mock<ICompanyRepository>()
Mock<IPersonRepository>() mockPersonRepository = new Mock<IPersonRepository>()
MyController sut;
Public MyControllerTests ()
{
// Create your "System under test" which is your MyController. Pass in your mock repositories to aid your testing.
sut = new MyController(mockCompanyRepository.Object, mockPersonRepository.Object)
}
[TestMethod]
public void SearchShouldGetCompaniesOnceWhereQueryIsNotEmpty
{
//Arrange
var expectedCompanies = new List<Company>{new Company{"Company1"}, new Company{"Company2"}};
//Setup mock that will return People list when called:
mockCompanyRepository.Setup(x => x.Get()).Returns(expectedCompanies);
mockPersonRepository.Setup(x => x.Get()).Returns(new List<Person>())
//Act
var result = sut.Search("Conway");
//Assert - check the company repository was called once and the result was as expected
mockCompanyRepository.Verify(x => x.Get(), Times.Once());
OkNegotiatedContentResult<string> conNegResult = Assert.IsType<OkNegotiatedContentResult<string>>(actionResult);
Assert.Equal("data: [{Name : "Company1"}, {Name : "Company2"}]", conNegResult.Content);
}
}
[TestClass]
公共类MyControllerTests
{
Mock()mockCompanyRepository=新建Mock()
Mock()mockPersonRepository=新建Mock()
霉菌控制素;
公共MyControllerTests()
{
//创建您的“测试中的系统”,这是您的MyController。传入您的模拟存储库以帮助您进行测试。
sut=新的MyController(mockCompanyRepository.Object、mockPersonRepository.Object)
}
[测试方法]
公共无效搜索应获取公司,查询不为空
{
//安排
var ExpectedCompanys=新列表{新公司{“Company1”},新公司{“Company2”};
//调用时将返回人员列表的安装程序模拟:
mockCompanyRepository.Setup(x=>x.Get()).Returns(expectedcompanys);
mockPersonRepository.Setup(x=>x.Get()).Returns(new List())
//表演
var result=sut.Search(“康威”);
//断言-检查公司存储库被调用一次,结果与预期一致
mockCompanyRepository.Verify(x=>x.Get(),Times.Once());
OkNegotiatedContentResult conNegResult=Assert.IsType(actionResult);
相等(“数据:[{Name:“Company1”},{Name:“Company2”}]”,connegressult.Content);
}
}
您还没有在问题中包含存储库的代码,但是如果您使用上述样式,您应该