如何使用Autofixture创建和填充我的模拟类?

目前我正在使用EF6在UnitOfWork中实现我的存储库。 我还创建了一个In-Memory模拟实现(MockUnitOfWork和MockRepository),以便我可以在unit testing中使用它们,但是我现在必须处理对象的繁琐设置。

这不是Autofixture的设计目的吗? 我如何获得可以在包含FooBarr存储库的测试中使用的MockUnitOfWork? 我正在使用NSubstitute作为我的模拟框架。

IUnitOfWork

public interface IUnitOfWork { void Save(); void Commit(); void Rollback(); IRepository FooRepository { get; } IRepository BarRepository { get; } } 

IRepository

 public interface IRepository where TEntity : class { Func<IQueryable, IOrderedQueryable> orderBy = null, string includeProperties = ""); IEnumerable Get(Expression<Func> filter = null, Func<IQueryable, IOrderedQueryable> orderBy = null); TEntity GetByID(object id); void Insert(TEntity entity); void Delete(object id); void Delete(TEntity entityToDelete); void Update(TEntity entityToUpdate); } 

您正在尝试在此进行function测试,因此拥有一个function数据库是明智之举。

EF可以使用测试连接字符串在setup和teardown方法中重新创建和销毁数据库。 这将为您的测试提供真实的function测试环境,以防止模仿真实环境。

例如:

  [TestFixtureSetUp] public static void SetupFixture() //create database { using (var context = new XEntities()) { context.Setup(); } } [TestFixtureTearDown] public void TearDown() //drop database { using (var context = new XEntities()) { context.Database.Delete(); } } [SetUp] public void Setup() //Clear entities before each test so they are independent { using (var context = new XEntities()) { foreach (var tableRow in context.Table) { context.Table.Remove(tableRow); } context.SaveChanges(); } } 

是的,这正是它的设计目标。 请参阅下面的示例。 我正在使用Mock而不是NSubstitute,因为我不熟悉NSubstitute。 您只需要传递另一个自定义,并在设置中使用NSubstitute语法。

 [SetUp] public void SetUp() { // this will make AutoFixture create mocks automatically for all dependencies _fixture = new Fixture() .Customize(new AutoMoqCustomization()); // whenever AutoFixture needs IUnitOfWork it will use the same mock object // (something like a singleton scope in IOC container) _fixture.Freeze>(); // suppose YourSystemUnderTest takes IUnitOfWork as dependency, // it'll get the one frozen the line above _sut = _fixture.Create(); } [Test] public void SomeTest() { var id = _fixture.Create(); // some random id var fooObject = _fixture.Create(); // the object repository should return for id // setuping THE SAME mock object that wa passed to _sut in SetUp. // _fixture.Freeze>() returns the mock object, so whatever comes // next is Mock specific and you'll have to use NSubstitute syntax instead _fixture.Freeze>() .Setup(uow => uow.FooRepository.GetById(id)) .Returns(fooObject); // if this method will ask the unit of work for FooRepository.GetById(id) // it will get fooObject. var whatever = _sut.SomeMethod(id); // do assertions } 

关于AutoFixture的美妙之处在于,您不必为所测试系统的所有依赖项创建模拟。 如果您正在测试仅使用一个依赖项的function,则只需创建被测系统之前冻结它。 其余的依赖项将自动进行模拟。