在单元测试中模拟Automapper是一种好习惯吗?

时间:2016-10-12 12:02:12

标签: c# unit-testing mocking automapper software-design

这个代码库中我们使用了automapper,并且有2层DomainService。每个都有其数据表示对象DomainItemServiceItem。该服务从域获取数据,使用构造函数注入的automapper实例来映射

class Service 
{
  public ServiceItem Get(int id)
  {
    var domainItem = this.domain.Get(id);
    return this.mapper.Map<DomainItem, ServiceItem>(domainItem);
  }
}

假设最佳实践,因此mapper没有副作用,也没有外部依赖。您可以编写一个静态函数,在几秒钟内将一个对象转换为另一个对象,只需映射字段。

考虑到这一点,在这样的单元测试中模拟映射器是一个好习惯吗?

[TestClass]
class UnitTests
{
  [TestMethod]
  public void Test()
  {
    var expected = new ServiceItem();

    var mockDomain = new Mock<IDomain>();
    // ... setup
    var mockMapper = new Mock<IMapper>();
    mockMapper.Setup(x => x.Map<DomainItem, ServiceItem>(It.IsAny<DomainItem>()))
      .Returns(expected);


    var service = new Service(mockDomain.Object, mockMapper.Object);
    var result = service.Get(0);

    Assert.AreEqual(expected, result);
  }
}

对我来说,似乎这样的单元测试并没有真正带来任何价值,因为它只是有效地测试了模拟,所以我要么根本不写它或者我使用实际的映射器而不是嘲笑的人。我是对的,还是忽略了什么?

1 个答案:

答案 0 :(得分:7)

我认为这里的问题是,测试是针对实际尝试实现的内容编写的,正在测试Service.Get()

我写这个测试的方式如下:

[TestMethod]
public void Test()
{
  var expected = new ServiceItem();

  var mockDomain = new Mock<IDomain>();
  var expectedDomainReturn = new DomainItem(0); //Illustrative purposes only
  mockDomain.Setup(x => x.DomainCall(0)).Returns(expectedDomainReturn); //Illustrative purposes only

  var mockMapper = new Mock<IMapper>();
  mockMapper.Setup(x => x.Map<DomainItem, ServiceItem>(It.IsAny<DomainItem>()))
      .Returns(expected);    


  var service = new Service(mockDomain.Object, mockMapper.Object);
  var result = service.Get(0);

  mockDomain.Verify(x => x.DomainCall(0), Times.Once);
  mockMapper.Verify(x => x.Map<DomainItem, ServiceItem>(expectedDomainReturn), Times.Once);
}

此测试不是没有真正检查service.Get()的功能,而是根据响应检查传递的参数对于各个依赖调用是否正确。因此,您不会自己测试AutoMapper,也不需要。

检查result基本没用,但会让代码覆盖率更高。