我目前正在与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");
}
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 :(得分: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;});
您还可以合并所有方法。
答案 1 :(得分:2)
MyTableDTO
返回的GetDTO
是新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);
的确切值:
public static void main(String[] args) {
JSONParser parser = new JSONParser();
try {
Object obj = parser.parse(new FileReader("src/bikes.json"));
JSONObject jsonObject = (JSONObject) obj;
//System.out.println(jsonObject);
JSONArray bikeList = (JSONArray) jsonObject.get("BikeList");
Iterator<String> iterator = bikeList.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}