[英]How to unit test a repository pattern that uses Entity Framework?
I'm currently trying to unit test a repository I made through Entity Framework: 我目前正在尝试对通过Entity Framework进行的存储库进行单元测试:
What I want to happen is that test the repository without actually sending/connecting to the actual database, I want to this without using any mocking framework. 我想要发生的是测试存储库而不实际发送/连接到实际的数据库,我想这样做而不使用任何模拟框架。
Currently my test is sending the data to the database, what I want to happen is test the add/remove etc. methods without sending the actual data to the database since it's only for testing. 目前我的测试是将数据发送到数据库,我想要发生的是测试添加/删除等方法而不将实际数据发送到数据库,因为它仅用于测试。
Here is the repository: 这是存储库:
namespace AbstractFactory.Repository
{
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
/// <summary>
/// This class serves as the structure of the Author repository using a database
/// </summary>
public class DbAuthorRepository : IRepository<AuthorEntity>
{
private AbstractFactoryPatternEntities context;
public DbAuthorRepository(AbstractFactoryPatternEntities context)
{
this.context = context;
}
/// <summary>
/// Adds the specified author.
/// </summary>
/// <param name="author">The author.</param>
public void Add(AuthorEntity author)
{
context.AuthorEntities.Add(author);
}
/// <summary>
/// Removes the specified author.
/// </summary>
/// <param name="author">The author.</param>
public void Remove(AuthorEntity author)
{
this.context.AuthorEntities.Remove(author);
}
/// <summary>
/// Saves this instance.
/// </summary>
public void Save()
{
this.context.SaveChanges();
}
/// <summary>
/// Gets all.
/// </summary>
/// <returns>returns a list of all the authors</returns>
public IEnumerable<AuthorEntity> GetAll()
{
List<AuthorEntity> result = this.context.AuthorEntities.Include(a => a.Books).ToList();
return result;
}
/// <summary>
/// Gets the author by id.
/// </summary>
/// <param name="id">The id.</param>
/// <returns>returns an entity</returns>
public AuthorEntity GetById(int id)
{
AuthorEntity result = this.context.AuthorEntities.Single(a => a.AuthorId == id);
return result;
}
}
}
Here is the current code for the unit test: 以下是单元测试的当前代码:
[TestMethod]
public void Add_MethodIsCalled_EntityCountIsIncrementedByOne()
{
using (ShimsContext.Create())
{
ShimAbstractFactoryPatternEntities context = new ShimAbstractFactoryPatternEntities(new AbstractFactoryPatternEntities());
DbAuthorRepository repository = new DbAuthorRepository(context);
repository.Add(new AuthorEntity { FirstName = "Test", LastName = "testing=" });
var actual = repository.GetAll().Count();
repository.Save();
var expected = repository.GetAll().Count();
Assert.AreNotEqual(actual, expected);
}
//AbstractFactoryPatternEntities context = new AbstractFactoryPatternEntities();
//DbAuthorRepository repository = new DbAuthorRepository(context);
//var actual = repository.GetAll().Count();
//repository.Add(new AuthorEntity { FirstName = "Testing", LastName = "MyTest" });
//repository.Save();
//var expected = repository.GetAll().Count();
//Assert.AreNotEqual(actual, expected);
}
[TestMethod]
public void Remove_MethodIsCalled_EntityCountRemainsTheSame()
{
AbstractFactoryPatternEntities context = new AbstractFactoryPatternEntities();
DbAuthorRepository repository = new DbAuthorRepository(context);
AuthorEntity newAuthor = new AuthorEntity { FirstName = "Testing", LastName = "MyTest" };
repository.Add(newAuthor);
repository.Save();
var actual = repository.GetAll().Count();
Console.WriteLine(actual);
repository.Remove(newAuthor);
var expected = repository.GetAll().Count();
Console.WriteLine(expected);
Assert.AreEqual(actual, expected);
}
[TestMethod]
public void Get_MethodIsCalled_CorrectAuthorIsRetrieved()
{
AbstractFactoryPatternEntities context = new AbstractFactoryPatternEntities();
DbAuthorRepository repository = new DbAuthorRepository(context);
int target = 4;
AuthorEntity author = repository.GetById(target);
Assert.AreEqual(target, author.AuthorId);
}
I want to use shims/stub/fakes in order to make the test. 我想使用shims / stub / fakes来进行测试。
The Entity Framework repository is a concrete implementation of your repository interface. 实体框架存储库是存储库接口的具体实现。 Because it is concrete, you can't abstract it and test without the database - the whole point of this concrete implementation is to write the data to the database! 因为它是具体的,你不能抽象它并在没有数据库的情况下进行测试 - 这个具体实现的重点是将数据写入数据库!
This means that testing EF repositories should rather aim at verifying that repositories write to actual database - in the act phase of your test you invoke repository methods and in the assert phase you use any other way of getting the data from the database (ado.net perhaps?) to check if the repository does its job. 这意味着测试EF存储库的目的应该是验证存储库是否写入实际数据库 - 在测试的行为阶段调用存储库方法,在断言阶段,您可以使用任何其他方式从数据库获取数据(ado.net)或许?)检查存储库是否完成了它的工作。
Yet another, unrelated thing is that you can have another implementation of the repository which uses an in-memory data store and injecting such in-memory repository to other services allows you to test these services wihout writing to a physical database. 另一个不相关的事情是,您可以使用内存数据存储的另一个存储库实现,并将这样的内存存储库注入其他服务,允许您在不写入物理数据库的情况下测试这些服务。 You could even mock a repository injected to other services just to perform some behavioral tests, ie test whether your services use your repositories correctly. 您甚至可以模拟注入其他服务的存储库,只是为了执行一些行为测试,即测试您的服务是否正确使用您的存储库。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.