【问题标题】:How I can test a particular method in my Service class using Mock C#?如何使用 Mock C# 在我的服务类中测试特定方法?
【发布时间】:2016-09-29 17:26:57
【问题描述】:

请帮我解决我的问题。我有一个服务类,如下所示:

public class RateService:IRatesService
{
    ...
    public RatesDTO GetById(int Id)
    {
        return Mapper.Map<Rates, RatesDTO>(this.db.Rates.GetAll().Where(m => m.RateId == Id).First());
    }
}

一个接口 IRatesService 看起来像那个代码示例:

public interface IRatesService
{
    .....
    RatesDTO GetById(int Id);
    ....
}

现在我尝试测试公共 RatesDTO GetById(int Id) 方法。我的代码如下:

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        Mock<IRatesService> mock = new Mock<IRatesService>();
        mock.Setup(m => m.GetById(It.IsAny<int>())).Returns<RatesDTO>(total=>total);

        Assert.IsNotNull(mock.Object.GetById(1));
    }
}

但是当我运行测试时,我收到如下错误:

测试名称:TestMethod1 测试
全名:Provider.Tests.Services.UnitTest1.TestMethod1

结果消息:

测试方法 Provider.Tests.Services.UnitTest1.TestMethod1 抛出 异常:System.ArgumentException:Невозможно преобразовать объект типа "System.Int32" к типу "Provider.BLL.DTO.RatesDTO"。

测试服务类和方法的最佳实践是什么?

【问题讨论】:

  • 如果您尝试测试 RateService,您应该测试具体类并且不应该模拟它。模拟存在于您想要单独测试类的情况下,因此您可以模拟类所依赖的对象。

标签: c# unit-testing


【解决方案1】:

您正在尝试测试您的模拟。这没有任何意义。

您应该努力测试您的实际代码。 在您的情况下,您可能希望确保您的 GetById 返回带有正确 id 值的 RatesDTO。

您可以使用 Mock 框架,以方便您的测试。 例如如果您正在尝试执行单元测试并且您正在使用数据库层,您可能想要模拟数据库层 GetAll 函数并返回几个对象,然后运行测试以检查您是否实际返回正确的对象(相同的 id)。

【讨论】:

    【解决方案2】:

    您的RateService 是被测系统。在为单元测试创​​建模拟时,规范是模拟被测系统的依赖项。

    因此,鉴于您当前的服务,假设它依赖于数据存储。

    public class RateService : IRatesService {
        private readonly IDbContext db;
        public RateService(IDbContext dbContext) {
            this.db = dbContext;
        }
        //...
        public RatesDTO GetById(int Id) {
            return Mapper.Map<Rates, RatesDTO>(this.db.Rates.GetAll().Where(m => m.RateId == Id).First());
        }
        //...
    }
    

    IDbContext 将是被测系统的依赖项。

    你会在测试RateService时模拟它

    [TestClass]
    public class RateServiceUnitTests {
        [TestMethod]
        public void Given_ValidId_GetById_Should_Return_Dto() {
            //Arrange
            var validId = 1;
            var fakes = new List<Rates>() {
                new Rates { RateId = validId }
            };
            var mock = new Mock<IDbContext>();
            //Assuming IDbContext.Rates.GetAll() returns an IEnumerable<Rates>
            mock.Setup(m => m.Rates.GetAll()).Returns(fakes);
            var sut = new RateService(mock.Object);
            //Act
            var result = sut.GetById(validId);
            //Assert
            Assert.IsNotNull(result);
        }
    }
    

    注意到您也在使用映射器。您应该确保也为测试配置了它,否则测试将失败。在您的类中使用静态调用时,当您尝试隔离系统进行测试时,它们可能会导致问题。尝试将映射器也添加为依赖项。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-20
      • 2022-10-23
      • 2014-02-08
      • 1970-01-01
      • 2012-06-10
      • 1970-01-01
      • 2023-03-14
      • 1970-01-01
      相关资源
      最近更新 更多