c# - Task<IEnumerable<>> 自定义的 AutoFixture 自动设置返回类型

标签 c# unit-testing autofixture

我在测试中使用 AutoFixture 和 AutoMoqCustomization。

我有一个服务是被测系统的依赖项:

ISomeService
{
    Task<IEnumerable<int>> Get();
}

我在被测系统内部调用它:

var collection = await _someService.Get(); // collection is empty

我不关心集合中的内容,但我需要集合不是 为空。我这样做:

_fixture.Freeze<Mock<ISomeService>>()
            .Setup(service => service.Get())
            .Returns(Task.FromResult(_fixture.CreateMany<int>()));

看起来应该通过定制来完成。我创建并注册了一个:

public class TaskCollectionCustomization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Customizations.Add(
            new FilteringSpecimenBuilder(
                new TaskCollectionBuilder(),
                new GenericTypeSpecification(typeof(Task<>))));
    }

    private class TaskCollectionBuilder : ISpecimenBuilder
    {
        public object Create(object request, ISpecimenContext context)
        {
            // never enters here
        }
    }
}

问题是从未输入它的 Create 方法。有任何想法或现成的解决方案吗?

编辑

添加GenericTypeSpecification源

public class GenericTypeSpecification : IRequestSpecification
{
    private readonly Type _type;

    public GenericTypeSpecification(Type type)
    {
        _type = type;
    }

    public bool IsSatisfiedBy(object request)
    {
        var requestedType = request as Type;

        return requestedType != null &&
               requestedType.IsGenericType &&
               requestedType.GetGenericTypeDefinition() == _type;
    }
}

最佳答案

AutoFixture 已经支持开箱即用的任务,这一点证明了这一点 Characterization Test :

[Fact]
public void AutoFixtureAlreadySupportsTasks()
{
    var fixture = new Fixture();
    var t = fixture.Create<Task<IEnumerable<int>>>();
    Assert.NotEmpty(t.Result);
}

因此,您只需要配置一个 Test Double你的服务是这样的:

[Fact]
public void ConfigureMock()
{
    var fixture = new Fixture().Customize(new AutoMoqCustomization());
    fixture.Freeze<Mock<ISomeService>>()
        .Setup(s => s.Get())
        .Returns(fixture.Create<Task<IEnumerable<int>>>());

    var svc = fixture.Create<ISomeService>();

    Assert.NotEmpty(svc.Get().Result);
}

如果您认为这工作量太大,您也可以要求 AutoConfiguredMoqCustomization 为您做这些,就像这样:

[Fact]
public void SimplestCustomization()
{
    var fixture = 
        new Fixture().Customize(new AutoConfiguredMoqCustomization());
    var svc = fixture.Create<ISomeService>();
    Assert.NotEmpty(svc.Get().Result);
}

但是,就我个人而言,我不是自动配置的测试替身的忠实拥护者,因为我相信 explicit is better than implicit和 Test Double 配置应该是单元测试的显式部分,因为它描述了 Indirect Input用于测试用例。

关于c# - Task<IEnumerable<>> 自定义的 AutoFixture 自动设置返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28876897/

相关文章:

c# - Linq 用于使用 group 和 orderby 计算排名

c# - .NET Framework 4.5 上的意外加速

reactjs - 如何避免 React Jest 测试中的 "False positive"覆盖率

c# - 无法掌握 Freeze/Inject/Register 之间的区别

c# - 模拟 IHttpClientFactory - xUnit C#

c# - COM 库初始化失败,C# 代码为 0x80010106

c# - 如何使用 'out' 参数测试方法?

ios - 我如何在 Xcode 7.3 中启动非托管测试?

c# - 如何在单元测试中使用 AutoData 在测试参数中提供一个类型的 N 个对象?

c# - 自动模拟 SUT