2017-08-03 42 views
2

我目前正在與Moq一起做一些單元測試。我遇到了一個問題,即我指定了我的模擬對象返回的內容,但實際的調用返回的是null,而不是我在.Returns(...)中指定的內容。我查看了其他職位,其中一條建議是與MockBehavior.Strict創建模擬 - 這樣做後,我得到了相當詳細的錯誤如下:MOQ'd對象返回null,儘管指定.Returns

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

上唯一然而,我打電話設置方法,我的嘲弄的對象已經調用。請看下面的代碼:

我的測試:

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"); 
    } 

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; 
    } 

爲什麼在我的測試中嘲笑回購也不回我在.Returns(..)調用指定的值?所有的幫助表示讚賞。

編輯:根據要求,這裏是MyRepository.Save方法和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

你能告訴'Repository.Save()'方法? –

+0

請包含'GetDto'的源代碼。 – mjwills

+0

@RomaDoskoch更新,以顯示要求 – GregH

回答

3

你得到null因爲GetDto()收益從myDto對象的不同 - 引用是不同的。

你可以改變你的Setup()返回myDto

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

或者,如果你想返回被作爲參數傳遞的對象:

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

或者,如果你想模擬基於一些屬性:

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

或者如果你想修改返回結果:

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

您也可以合併所有方法。

2

通過GetDTO返回的MyTableDTO是一個新的MyTableDTO這是不一樣的Setup規則,因爲它有一個不同的參考,因此不存在匹配設置爲Save

相反,你可以嘗試這樣的:

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

或者,如果你不關心傳遞給Save精確值:

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