使用模拟存储库对象测试服务

本文关键字:对象 测试 服务 存储 模拟 | 更新日期: 2023-09-27 18:15:58

我正在测试一个框架内的服务。

为了初始化服务,我使用模拟存储库对象。

ServiceTest.cs

private IRepository _repository;
private IService _service;
private List<Object> _objects;
[TestInitialize]
public void Initialize()
{
  _repository = new Mock<IRepository>().Object;
  _service = new Service(repository);
  _objects = new List<Object>()
  {
      new Object { Name = "random", ID = 1 },
      new Object { Name = "not so random", ID = 1},
      new Object { Name = "random", ID = 2 },
      new Object { Name = "not so random", ID = 2}
  };
  //attempt at mocking the repository
  _repository.Setup(r => r.GetObjects(It.IsAny<string>(), It.IsAny<int>())).Returns(_objects.Where(o => o.Name == _objects.Name && o.ID == _objects.ID).ToList());
}
[TestMethod]
public void GetObjects_ReturnObjectsList()
{
    //Arrange
    var name = "random";
    //Act
    var objects = _service.RetrieveObjects(name, 2);
    //Assert
    Assert.AreEqual(name, objects.Single().Name);
 }

然而,当我测试服务时,我得到的是ArgumentNullExceptions。设置为存储库方法的变量调用返回null,并最终在运行业务逻辑时抛出错误。

Service.cs

    public List<Objects> RetrieveObjects(string name, int id) 
    {   
      var getObjects = repository.GetObjects(name, id); //getObjects return null
      DoLogic(getObjects); //ArgumentNullException is thrown here
      return getObjects; 
    }

我已经查找了关于模拟存储库的信息,但似乎我将有很多设置只是为了测试。我想知道这样的设置是否值得。

为什么我得到ArgumentNullExceptions ?是否有一种方法可以测试调用存储库的方法?

使用模拟存储库对象测试服务

您只需要设置正在测试的内容,因此在您的安排中执行如下操作:

var repository = new Mock<IRepository>();
repository.Setup(x => x.GetObjects(It.IsAny<string>()).Returns("whatever getobjects should be returned, maybe a mock object or string");
var service = new Service(repository.Object());
//Continue your test
var entity1 = new MyEntity();
var entity2 = new MyEntity();
var entities = new List<MyEntity>{entity1, entity2};
var mockRepository = new Mock<IRespository>();
mockRepository.Setup(r => r.GetObjects("some param")).Returns(entities);
var service = new Service(mockRepository.Object);
service.DoWork("some param");
//continue the test

您应该单独测试SUT(被测试对象)。不要尝试模拟现有的类,只使用接口。这样你就不会依赖于其他可能有bug的对象。通常,您将无法设置用作模拟的现有类的回调和返回。mock接口允许您控制和预测返回值。

所以在你的特殊情况下,你应该按照@ianaldo21的建议做,我只是把第一行改为:

var repository = new Mock<IRepository>();

,然后进行设置,并传递存储库。Object to Service.

您不应该断言SUT的状态,而应该测试SUT与其他对象的行为和交互。所以你可以这样写:

repository.Verify(x => x.GetObjects("test"));