2017-08-03 1 views
2

Je travaille actuellement avec Moq pour faire des tests unitaires. Je rencontre un problème où je spécifie ce que mon objet raillé renvoie, mais l'appel réel renvoie null au lieu de ce que je spécifie dans .Returns(...). J'ai examiné d'autres postes et une des suggestions était de créer la maquette avec MockBehavior.Strict - après avoir fait cela, je reçois une erreur assez bavard comme suit:Objet MOQ retournant null en dépit de la spécification. Retourne

IMyRepository.Save(MvcIndividualAuth.Data.Models.DTO.MyTableDTO) invocation failed with mock behavior Strict. All invocations on the mock must have a corresponding setup.

Cependant, je fais appel à la seule configuration méthode que mon objet moqué appelle déjà. S'il vous plaît voir le code ci-dessous:

Mon test:

MyService _myService; 
    Mock<IMyRepository> _myRepoMock; 

    [TestInitialize] 
    public void Setup() 
    { 
     _myRepoMock = new Mock<IMyRepository>(); 
     _myService = new MyService(_myRepoMock.Object); 
    } 

[TestMethod] 
    public void MyServiceSave() 
    { 
     //Arrange 
     var myDto = new MyTableDTO { Id = 1, Bar = 5, Foo = "Test" }; 
     _myRepoMock.Setup(x => x.Save(myDto)).Returns(myDto); 

     //Act 
     var vm = _myService.Save(new MyTableViewModel(myDto)); 

     //Assert 
     Assert.AreEqual(vm.Id, 1); 
     Assert.AreEqual(vm.Foo, "Test"); 
     Assert.AreEqual(vm.Bar, 5); 
     Assert.AreEqual(vm.BarPlusFoo, "5 Test"); 
    } 

méthode MyService.Save:

public MyTableViewModel Save(MyTableViewModel viewModel) 
    { 
     var dto = MyTableViewModel.GetDto(viewModel); 
     var dbDto = _myRepo.Save(dto); //_myRepo is of type IMyRepository, 
             // this _myRepo.Save call is returning null 

     var vm = new MyTableViewModel(dbDto); 

     return vm; 
    } 

Pourquoi le repo moqué dans mon test ne pas retourner la valeur que je précise dans mon .Returns(..) appel? Toute aide est appréciée.

EDIT: sur demande, voici la méthode MyRepository.Save et MyTableViewModel.GetDto():

MyRepository.Save:

public MyTableDTO Save(MyTableDTO dto) 
    { 
     try 
     { 
     var entity = new MyTable(); 

     if (String.IsNullOrEmpty(dto.Foo)) 
     { 
      throw new ArgumentException("MyTable requires Foo"); 
     } 

     if (dto.Id == 0) 
     { 
      //added 
      entity.Update(dto); 
      _db.MyTables.Add(entity); 
     } 
     else 
     { 
      //modified 
      entity = _db.MyTables.Single(x => x.Id == dto.Id); 

      entity.Update(dto); 
     } 

     _db.SaveChanges(); 

     return new MyTableDTO(entity); 
     } 
     catch (Exception) 
     { 
     throw; 
     } 
    } 

MyTableViewModel.GetDto (..);

public static MyTableDTO GetDto(MyTableViewModel vm) 
    { 
     var dto = new MyTableDTO 
     { 
     Bar = vm.Bar, 
     Foo = vm.Foo, 
     Id = vm.Id 
     }; 

     return dto; 
    } 
+0

Pourriez-vous montrer la méthode 'Repository.Save()' ? –

+0

Veuillez inclure le code source de 'GetDto'. – mjwills

+0

@RomaDoskoch mis à jour pour afficher la demande – GregH

Répondre

3

Vous obtenez null parce que GetDto() Retourne un objet différent de myDto - références sont différentes.

Vous pouvez changer votre Setup() retourner myDto:

_myRepoMock.Setup(x => x.Save(It.IsAny<MyTableDTO>())).Returns(myDto); 

Ou si vous voulez retourner l'objet qui a été passé en paramètre:

_myRepoMock.Setup(x => x.Save(It.IsAny<MyTableDTO>())).Returns((MyTableDTO dto) => dto); 

Ou si vous voulez Mock basé sur certains propriétés:

_myRepoMock.Setup(x => x.Save(It.Is<MyTableDTO>(dto => dto.Id == 1))).Returns(myDto); 

Ou si vous voulez modifier le filtre résultat:

_myRepoMock.Setup(x => x.Save(It.IsAny<MyTableDTO>())).Returns((MyTableDTO dto) => { dto.Id = 2; return dto;}); 

Vous pouvez également combiner toutes les approches.

2

Le MyTableDTO retourné par GetDTO est une nouvelle MyTableDTO qui n'est pas la même chose que la règle dans votre Setup, parce qu'il a une autre référence, donc il n'y a pas d'installation correspondant pour Save.

Au lieu de cela, vous pouvez essayer quelque chose comme:

_myRepo.Setup(s => s.Save(It.Is<MyTableDTO>(d => d.Equals(myDto))).Returns(myDto); 

Ou, si vous n'êtes pas préoccupé par les valeurs exactes transmises à Save:

_myRepo.Setup(s => s.Save(It.IsAny<MyTableDTO>()).Returns(myDto);