在AutoFixture中自定义抽象类的构造函数输入。

问题描述 投票:0回答:1

当我试图对一个服务方法进行单元测试时,它所实现的基本抽象类构造函数包含了2个参数。我想在使用Auto-fixture调用服务时自定义这些参数。

基本服务代码如下。

public abstract class ServiceBase : IHostedService, IDisposable
{
   private readonly CronExpression _expression;
   private readonly TimeZoneInfo _timeZoneInfo;

   protected BaseService(string cronExpression, TimeZoneInfo timeZoneInfo)
   {
      _expression = CronExpression.Parse(cronExpression);
      _timeZoneInfo = timeZoneInfo;
   }

   public abstract Task ExecuteTask(CancellationToken cancellationToken);
   .
   .
}

另一个服务从这个基础抽象类继承过来

public class TestService : ServiceBase
{
   public override async Task ExecuteTask(CancellationToken stoppingToken)
   {
      //Implementation here
   }
}

在我的单元测试中,我调用了 ExecuteTask 功能如下

Func<Task> executeAction = async () => await sut.ExecuteTask(A<CancellationToken>._);
executeAction.Should().NotThrow();

AutoFixture 试图将一个随机字符串传递给 CronExpression 构造参数 BaseService 类。问题是这样的 CronExpression 必须是特定的格式,否则在试图解析它时就会出现错误。CronExpression.Parse(cronExpression)

我如何为构造函数参数传递自定义值?

先谢谢你。

c# .net-core abstract-class mstest autofixture
1个回答
3
投票

AutoFixture不知道服务的域约束。string 参数到你的类中。这应该给出一个提示,也许这个类型不是最合适的类的参数。这是一个典型的例子 原始的迷恋.

你可能会增强你的服务,而不是直接接受封装了这是一个CronExpression的想法的类型。

protected ServiceBase(CronExpression cronExpression, TimeZoneInfo timeZoneInfo)
{
    _cronExpression = cronExpression;
    ...
}

这样一来,就能保证 BaseService 将通过一个有效的 CronExpression. 如果不是这样,那就创造出了 CronExpression 将已经失败。

您可能会认为我们只是简单地转移了问题:您现在如何告诉 AutoFixture 创建一个有效的 CronExpression?

将工作重心转移到建设的优势上。CronExpression 是,任何定制的创建一个有效的。CronExpression 现在 可重复使用 为任何其他需要的类型。这将减少未来任何最终需要该类型的测试的仪式。更不用说其他所有避免原始困扰的好处了。

关于告诉AutoFixture如何创建一个有效的 CronExpression,有很多选择。你可以直接注入一个有效的。

fixture.Inject(CronExpression.Parse("myValidCronExpression"));

如果你希望能够选择多个,你可以用... ElementsBuilder 来从一个有效值池中选择。

public void Test()
{
    var fixture = new Fixture();
    fixture.Customizations.Add(new ElementsBuilder<CronExpression>(
        new[] { "validExpr1", "validExpr2" }
        .Select(s => CronExpression.Parse(s))
        .ToArray()))
    ...
}

该类型的创建控制权最大的方式是创建一个实施方案。ISpecimenBuilder我在这个回答中就不说了。如果你想走这条路,这里和其他地方都有很多例子。

在对AutoFixture进行定制后,你的SUT就可以工作了。

var sut = fixture.Create<TestService>();

注:我还没有测试过 TimeZoneInfo 可以直接被 AutoFixture 的默认样本构建器实例化。如果不能,也可以使用类似的方法来实现该类型。

© www.soinside.com 2019 - 2024. All rights reserved.