I am trying to setup tests for my new projects and come across some difficulties.
I am using NUnit and Rhino Mocks.
The Code that I am trying to test is this
you need to mock or stub all of the components which you do not want to test. You should, as a rule of thumb only have a maximum of single mock object the rest should be stubs. Mock the things you want to verify interaction with and stub the things which you just want to provide data for your test.
you don't tell us what type your _documentRepository is so its hard to tell exactly what you are testing here, but to test this method the only thing you can do, IMHO, is check that if the IsDirty flag is set is check that the correct methods on the _documentRepository and the Context are called.
To do this I would create a mock _documentRepository and mock DbContext and set expectations that _documentRepository.SaveOrUpdate(document)
is called with the document passed in. Actually looking again at the code you need to convert between the dto and the document. Currently this is being done in a method. I would create a interface and a class for this and make that interface a dependency of the class you are testing so that you can create a stub which returns a known document from the documentDto. This class could handle creating a new document or returning an existing one based on the id in the Dto. otherwise you'll have to know what type of document is returned.
something like:
var documentDto = new NctsDepartureNoDto();
documentDto.IsDirty = true;
documentDto.Id = 0;
IDbContext context = MockRepository.GenerateMock();
context.Expect(x=>x.BeginTransaction()).Return(MockRepository.GenerateStub());
context.Expect(x=>x.CommitChanges());
then create a mock for the repository
IDocumentRepository repo = MockRepository.GenerateMock();
repo.Expect(x=>x.DbContext).Return(context).Repeat().Any();
repo.Expect(x=>x.SaveOrUpdate(Arg.Is.Any())).Return(MockRepository.GenerateStub);
This tests that you interact with the repository object correctly when the dirty flag is set. It shouldn't test that the document is saved correctly or that the correct document is returned when SaveOrUpdate
is called, as this should be tested in the tests for the repository, not here.
'But wait!' I hear you cry, 'you said at the beginning that there should only be a single mock, and here we have 2!'. That's true, and I think that this shows a fault in your current design.
You should not, I don't think, be exposing the DBContext from your documentRepository. You seem to be doing so in order to use the transactions.
If your repository needs to be aware of the transactions then have methods on the repository that allow the transactions to be controlled (or hide the fact that the transactions exist inside the repository object completely). These methods might just delegate to the internal DbContext but it would then mean that the only mock would need to be the document repository object itself, and not the DbContext