我有以下代码:
public interface IFlowFolderHandler
{
OperationResult Post(FlowFolder dto);
}
public class FlowFolderHandler : IFlowFolderHandler
{
private readonly IResponse m_response;
private readonly IEntityRepository m_entityRepository;
public FlowFolderHandler(IResponse response, IEntityRepository entityRepository)
{
m_response = response;
m_entityRepository = entityRepository;
}
public OperationResult Post(FlowFolder dto)
{
var ent = FlowFolderX.Cast(dto, true);
m_entityRepository.Update(ent);
var id = EntityIdComparer.IdToString(ent.Id);
m_response.Headers["X-Entity-Id"] = id;
return new OperationResult.Created
{
RedirectLocation = new Uri("FlowFolder/" + id, UriKind.Relative),
ResponseResource = ent.GetEntityRelation(),
};
}
}
我希望使用FlowFolderHandler.Post
和IResponse
模拟对IEntityRepository
方法进行单元测试。我目前的实现是使用以下手动模拟:
private class EntityRepositoryMock : IEntityRepository
{
private readonly Action<IEntityBase> m_update;
public EntityRepositoryMock(int id, EntityRelation entityRelation)
{
m_update = ent => EntityRepository.ApplySaveSideEffects(ent, id, entityRelation);
}
public IEntityBase Fetch(EntityId entityId) { throw new NotImplementedException(); }
public void FetchByExpression(Type entityType, Expression expr, IList list, List<Pair<string, bool>> orderBy) { throw new NotImplementedException(); }
public void Update(IEntityBase entity) { m_update(entity); }
}
private class ResponseMock : IResponse
{
public ResponseMock() { Headers = new HttpHeaderDictionary(); }
public IHttpEntity Entity { get { throw new NotImplementedException(); } }
public HttpHeaderDictionary Headers { get; private set; }
public void WriteHeaders() { throw new NotImplementedException(); }
public bool HeadersSent { get { throw new NotImplementedException(); } }
public int StatusCode
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
}
单元测试是:
[Test]
[Factory("YieldPostFlowFolderData")]
public void PostFlowFolder(int id, Uri uri, EntityRelation entityRelation, FlowFolder flowFolder)
{
var entityRepository = new EntityRepositoryMock(id, entityRelation);
var response = new ResponseMock();
var handler = new FlowFolderHandler(response, entityRepository);
var result = handler.Post(flowFolder);
Assert.AreEqual((int)HttpStatusCode.Created, result.StatusCode);
Assert.AreEqual(id, int.Parse(response.Headers["X-Entity-Id"]));
Assert.AreEqual(uri, result.RedirectLocation);
SUC.Utils.AssertDeepEqual(entityRelation, result.ResponseResource);
}
我的问题是如何在没有使用Rhino.Mocks的手动模拟EntityRepositoryMock
和ResponseMock
的情况下编写相同的单元测试(或多或少)?
感谢。
修改
我的手动模拟只包含构造函数,因为它们是手动模拟。我可以添加一个专用的方法PrepareMock
而不是构造函数,以确保模拟已准备好...模拟。自动模拟,由Rhino.Mocks创建的模拟,不会有任何与构造函数相关的问题,因为我会模拟接口而不是具体类型。
答案 0 :(得分:2)
// Mocks
var repositoryMock = MockRepository.GenerateMock<IEntityRepository>();
var responseMock = MockRepository.GenerateMock<IResponse>();
使用Expect()可以设置你想要的任何期望,例如exp [update()方法的ectation,它只是一个做某事而不是抛出异常:
repositoryMock.Expect(m => m.Update(null)).IgnoreArguments.WhenCalled(
mi =>
{
IEntityBase passedInEntity = mi.Args[0] as IEntityBase;
EntityRepository.ApplySaveSideEffects(passedInEntity, id, entityRelation);
}
).Repeat.Any();
另一个重点是模拟属性,您应该指定PropertyBehaviour()
:
repositoryMock.Expect(m => m.Entity).Proeprtybehaviour();
编辑:检查该方法是否曾被调用
repositoryMock.AssertWasCalled(m => m.Update(), mi => mi.Repeat.Once());
有用的链接:
答案 1 :(得分:0)
出于好奇,您的“手动”嘲笑是否会给您带来麻烦,或者您只是在寻找更清洁的方式来实施它们?有时候,“手动”方式是最好的(最简单的)方式,因为大多数模拟框架都有自己的问题。
无论如何,说完了,像你一样嘲笑类的基本步骤:
这里记录了Do()处理程序: http://ayende.com/wiki/Rhino+Mocks+The+Do()+Handler.ashx
您的模拟对象在构造函数中也有代码。仅供参考,您可能会遇到构造函数的一些问题。来自Ayende:
模拟类的技术限制是创建一个 由于mock,mock对象调用目标类构造函数 来自目标类。
这是来自这个讨论ctors的页面: http://ayende.com/wiki/Rhino+Mocks+Mocking+classes.ashx