尽管指定了 .Returns,最小起订量对象仍返回 null

Gre*_*egH 3 .net c# asp.net unit-testing moq

我目前正在与 Moq 合作进行一些单元测试。我遇到了一个问题,我指定我的模拟对象返回什么,但实际调用返回 null 而不是我在.Returns(...). 我查看了其他帖子,其中一个建议是创建模拟MockBehavior.Strict- 这样做后,我收到一个相当详细的错误,如下所示:

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

但是,我正在对我的模拟对象已经调用的唯一方法调用 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");
    }
Run Code Online (Sandbox Code Playgroud)

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;
    }
Run Code Online (Sandbox Code Playgroud)

为什么我的测试中的模拟存储库没有返回我在调用中指定的值.Returns(..)?感谢所有帮助。

编辑:根据要求,这里是 MyRepository.Save 方法和 MyTableViewModel.GetDto():

我的存储库.保存:

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;
      }
    }
Run Code Online (Sandbox Code Playgroud)

MyTableViewModel.GetDto(..);

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

      return dto;
    }
Run Code Online (Sandbox Code Playgroud)

Rom*_*och 5

你得到的是null因为GetDto()返回对象不同于myDto- 引用是不同的。

您可以将您的更改Setup()为 return myDto

_myRepoMock.Setup(x => x.Save(It.IsAny<MyTableDTO>())).Returns(myDto);
Run Code Online (Sandbox Code Playgroud)

或者,如果您想返回作为参数传递的对象:

_myRepoMock.Setup(x => x.Save(It.IsAny<MyTableDTO>())).Returns((MyTableDTO dto) => dto);
Run Code Online (Sandbox Code Playgroud)

或者,如果您想基于某些属性进行模拟:

_myRepoMock.Setup(x => x.Save(It.Is<MyTableDTO>(dto => dto.Id == 1))).Returns(myDto);
Run Code Online (Sandbox Code Playgroud)

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

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

您还可以结合所有方法。