Test et simulation unitaires à l’aide de RhinoMocks

J’essaie de configurer des tests pour mes nouveaux projets et rencontre quelques difficultés.

J’utilise NUnit et Rhino Mocks.

Le code que j’essaie de tester est le suivant:

public DocumentDto SaveDocument(DocumentDto documentDto) { Document document = null; using (_documentRepository.DbContext.BeginTransaction()) { try { if (documentDto.IsDirty) { if (documentDto.Id == 0) { document = CreateNewDocument(documentDto); } else if (documentDto.Id > 0) { document = ChangeExistingDocument(documentDto); } document = _documentRepository.SaveOrUpdate(document); _documentRepository.DbContext.CommitChanges(); } } catch { _documentRepository.DbContext.RollbackTransaction(); throw; } } return MapperFactory.GetDocumentDto(document); } 

Et mon code de test est comme suit

 [Test] public void SaveDocumentsWithNewDocumentWillReturnTheSame() { //Arrange IDocumentService documentService = new DocumentService(_ducumentMockRepository, _identityOfSealMockRepository, _customsOfficeOfTransitMockRepository, _accountMockRepository, _documentGuaranteeMockRepository, _guaranteeMockRepository, _goodsPositionMockRepository); var documentDto = new NctsDepartureNoDto(); documentDto.IsDirty = true; documentDto.Id = 0; //Act var retDocumentDto = documentService.SaveDocument(documentDto); //Assert Assert.AreEqual(documentDto, documentDto); } private static IDbContext CreateMockDbContext() { var dbContext = MockRepository.GenerateMock(); // setup expectations for DbContext mock //dbContextMock.Expect(...) // bind mock of the DbContext to property of repository.DbContext _ducumentMockRepository.Expect(mock => mock.DbContext).Return(dbContext).Repeat.Any(); return dbContext; } 

J’ai besoin de passer un documentDto avec is is dirty set et de vérifier s’il renvoie le même object.

Donc, je pensais utiliser un stub au lieu d’une maquette.

Je dois savoir comment définir les attentes afin de pouvoir tester la logique du code.

vous devez vous moquer de tous les composants que vous ne voulez pas tester. En règle générale, vous ne devriez avoir qu’un maximum d’object simulé, le rest devrait être constitué de talons. Simulez les éléments avec lesquels vous souhaitez vérifier l’interaction et remplacez ceux pour lesquels vous souhaitez simplement fournir des données pour votre test.

vous ne nous dites pas de quel type est votre _documentRepository, il est donc difficile de dire exactement ce que vous testez ici, mais pour tester cette méthode, la seule chose que vous pouvez faire, à mon humble avis, est de vérifier que, si l’indicateur IsDirty est défini, vérifiez que la les méthodes correctes sur le _documentRepository et le contexte sont appelées.

Pour ce faire, je créerais un modèle _documentRepository et un modèle DbContext, ainsi que les attentes que _documentRepository.SaveOrUpdate(document) est appelé avec le document transmis. _documentRepository.SaveOrUpdate(document) en réalité le code que vous devez convertir entre le dto et le document. Actuellement, cela se fait dans une méthode. Je créerais une interface et une classe pour cela et ferais de cette interface une dépendance de la classe que vous testez afin que vous puissiez créer un stub qui retourne un document connu à partir du documentDto. Cette classe peut gérer la création d’un nouveau document ou le retour d’un document existant en fonction de l’id du Dto. sinon, vous devrez savoir quel type de document est renvoyé.

quelque chose comme:

 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()); 

puis créer une maquette pour le référentiel

 IDocumentRepository repo = MockRepository.GenerateMock(); repo.Expect(x=>x.DbContext).Return(context).Repeat().Any(); repo.Expect(x=>x.SaveOrUpdate(Arg.Is.Any())).Return(MockRepository.GenerateStub); 

Ceci teste que vous interagissez correctement avec l’object de référentiel lorsque l’indicateur modifié est défini. Il ne faut pas vérifier que le document est enregistré correctement ou que le document correct est renvoyé lorsque SaveOrUpdate est appelé, car cela doit être testé dans les tests du référentiel, pas ici.

‘Mais attendez!’ Je vous entends pleurer, “vous avez dit au début qu’il ne devrait y avoir qu’un seul simulacre, et ici nous en avons 2!”. C’est vrai, et je pense que cela montre une faille dans votre conception actuelle.

Je ne pense pas que vous ne devriez pas exposer le DBContext de votre documentRepository. Vous semblez le faire pour pouvoir utiliser les transactions.

Si votre référentiel doit être informé des transactions, utilisez des méthodes permettant de contrôler les transactions (ou masquez le fait que les transactions existent complètement dans l’object de référentiel). Ces méthodes pourraient simplement déléguer au DbContext interne, mais cela signifierait alors que le seul modèle fictif devrait être l’object de référentiel de document lui-même, et non le DbContext.