.net 如何使用Rhino.Mocks模拟特定代码?
我有以下代码:.net 如何使用Rhino.Mocks模拟特定代码?,.net,mocking,rhino-mocks,.net,Mocking,Rhino Mocks,我有以下代码: public interface IFlowFolderHandler { OperationResult Post(FlowFolder dto); } public class FlowFolderHandler : IFlowFolderHandler { private readonly IResponse m_response; private readonly IEntityRepository m_entityRepository; public
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(),
};
}
}
我希望使用ireresponse
和IEntityRepository
模拟对FlowFolderHandler.Post
方法进行单元测试。我当前的实现使用以下手动模拟:
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(); }
}
}
我的问题是,如果没有使用Rhino.mock的手动mockEntityRepositoryMock
和ResponseMock
,如何编写相同的单元测试(或多或少)
谢谢
编辑
我的手动模拟只包含构造函数,因为它们是手动模拟。我可以添加一个专用的方法
PrepareMock
,而不是构造函数,以确保mock已经准备好。。。嘲笑。由Rhino.mocks创建的自动模拟不会有任何与构造函数相关的问题,因为我会模拟接口而不是具体类型。出于好奇,您的“手动”模拟会给您带来麻烦,还是您只是在寻找一种更干净的方法来实现它们?有时,“手动”方式是最好(最简单)的方式,因为大多数模拟框架都有自己的问题集
尽管如此,模仿类的基本步骤如下:
PropertyBehaviour()
:
编辑:检查方法是否被调用过一次
repositoryMock.AssertWasCalled(m => m.Update(), mi => mi.Repeat.Once());
有用的链接:
- 有关良好的示例和说明,请参见
responseMock.Expect(m=>m.Headers).PropertyBehavior();
不起作用,因为Headers
是只读属性。调用Headers
属性时,如何让模拟返回某个对象?抱歉,Repeat.Any()
。它指示即使多次调用方法也应返回指定的返回值,您可以通过Repeat.Once()将其转换为单个方法调用,这样下次调用mocked methiod时将返回null而不是返回值(显然对于返回类型不是void的方法),这适用于WhenCalled()
,它将在每次调用方法时执行,而不仅仅是第一次time@mark:关于属性,若要模拟返回值,请仅使用responseMock.Expect(m=>m.Headers).return(Myproperty)
并在Myproperty中抛出exception.Myproperty-测试类中定义的属性。若要测试异常,请使用Assert.Throws()=>responseMock.Headers)
很好,它可以工作。还有一个问题,我如何确保Update
方法只调用一次?
// Mocks
var repositoryMock = MockRepository.GenerateMock<IEntityRepository>();
var responseMock = MockRepository.GenerateMock<IResponse>();
repositoryMock.Expect(m => m.Update(null)).IgnoreArguments.WhenCalled(
mi =>
{
IEntityBase passedInEntity = mi.Args[0] as IEntityBase;
EntityRepository.ApplySaveSideEffects(passedInEntity, id, entityRelation);
}
).Repeat.Any();
repositoryMock.Expect(m => m.Entity).Proeprtybehaviour();
repositoryMock.AssertWasCalled(m => m.Update(), mi => mi.Repeat.Once());