我在模拟我的代码以使我能够测试我的 MVC 控制器时遇到了真正的问题。
我的存储库实现了以下接口
public interface IEntityRepository<T>
{
IQueryable<T> All { get; }
IQueryable<T> AllIncluding(params Expression<Func<T, object>>[] includeProperties);
void Delete(int id);
T Find(int id);
void InsertOrUpdate(T entity);
void InsertOrUpdateGraph(T entity);
}
像这样
public interface IMonkeyRepository : IEntityRepository<Monkey>
{
}
我的 EF 上下文实现了以下接口
public interface IMonkeyContext
{
IDbSet<Monkey> Monkeys { get; set; }
DbEntityEntry Entry(object entity);
IEnumerable<DbEntityValidationResult> GetValidationErrors();
int SaveChanges();
}
我的工作单元接口是这样定义的
public interface IUnitOfWork<TContext> : IDisposable
{
TContext Context { get; }
int Save();
}
并实施
public class MonkeyUnitOfWork : IUnitOfWork<IMonkeyContext>
{
private readonly IMonkeyContext context;
private bool disposed;
public MonkeyUnitOfWork(IMonkeyContext context)
{
this.context = context;
}
public IMonkeyContext Context
{
get
{
return this.context;
}
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
public int Save()
{
var ret = this.context.SaveChanges();
return ret;
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
((DbContext)this.context).Dispose();
}
}
this.disposed = true;
}
}
我有一个我想测试的创建动作的 MonkeyController。我被定义
if (this.ModelState.IsValid)
{
this.repo.InsertOrUpdate(Mapper.Map<MonkeyModel, Monkey>(monkey));
this.uow.Save();
return this.RedirectToAction(MVC.Monkey.Index());
}
return this.View(monkey);
在我的单元测试中,我使用 RhinoMocks 并定义了测试
[TestFixture]
public class MonkeyControllerTests
{
MockRepository mocks = null;
private IMonkeyRepository monkeyRepository;
private IMonkeyContext context;
private MonkeyUnitOfWork unitOfWork;
private MonkeyController controller;
[SetUp]
public virtual void SetUp()
{
TestHelpers.SetupAutoMap();
this.monkeyRepository = this.Mocks.StrictMultiMock<IMonkeyRepository>(typeof(IEntityRepository<Monkey>));
this.context = this.Mocks.StrictMock<IMonkeyContext>();
this.unitOfWork = new MonkeyUnitOfWork(this.context);
this.controller = new MonkeyController(this.MonkeyRepository, this.unitOfWork);
}
[TearDown]
public virtual void TearDown()
{
if (this.mocks != null)
{
try
{
this.mocks.ReplayAll();
this.mocks.VerifyAll();
}
finally
{
this.mocks = null;
}
}
}
public MockRepository Mocks
{
get
{
if (mocks == null)
mocks = new MockRepository();
return mocks;
}
}
[Test]
public void MonkeyCreateShouldShouldDoSomeStuff()
{
var monkeyModel = ViewModelTestHelpers.CreateSingleMonkey();
var monkey = Mapper.Map<MonkeyModel, Monkey>(monkeyModel);
this.monkeyRepository.Expect(action => action.InsertOrUpdate(monkey));
this.context.Expect(action => action.SaveChanges()).Return(1);
var result = (RedirectToRouteResult)this.controller.Create(monkeyModel);
Assert.AreEqual(MVC.Monnkey.ActionNames.Index, result.RouteValues["action"]);
}
}
当我运行测试时,我会收到以下错误
以前的方法 'IMonkeyContext.SaveChanges();' 需要返回值或抛出异常。
或者它抱怨 IEntityRepository.InsertOrUpdate 预期 1 实际 0
我已经尝试了很多演员表和咒语来让它发挥作用,但我很难过。有谁知道如何正确模拟这些对象?或者如果我从根本上错过了什么?