I have the following code:
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(),
};
}
}
I wish to unit test the FlowFolderHandler.Post
method, using IResponse
and IEntityRepository
mocks. My current implementation is using the following manual mocks:
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(); }
}
}
And the unit test is:
[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);
}
My question is how can I write the same unit test (more or less) without the manual mocks EntityRepositoryMock
and ResponseMock
using Rhino.Mocks?
Thanks.
EDIT
My manual mocks contain a constructor only because they are manual mocks. I could have added a dedicated method PrepareMock
instead of the constructor to make sure the mock is ready for ... mocking. Automatic mocks, the ones created by Rhino.Mocks, would not have any constructor related issues, because I would be mocking interfaces rather than concrete types.
// Mocks
var repositoryMock = MockRepository.GenerateMock<IEntityRepository>();
var responseMock = MockRepository.GenerateMock<IResponse>();
The using Expect() you can setup any expectation you want, for instance exp[ectation for the Update() method which is only one doing something rather than throwing exception:
repositoryMock.Expect(m => m.Update(null)).IgnoreArguments.WhenCalled(
mi =>
{
IEntityBase passedInEntity = mi.Args[0] as IEntityBase;
EntityRepository.ApplySaveSideEffects(passedInEntity, id, entityRelation);
}
).Repeat.Any();
Also one important point is mocking of the properties, you should specify PropertyBehaviour()
:
repositoryMock.Expect(m => m.Entity).Proeprtybehaviour();
EDIT: To check that method was called once
repositoryMock.AssertWasCalled(m => m.Update(), mi => mi.Repeat.Once());
Useful links: