Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 如何在AutoFixture中更新夹具的自定义_Unit Testing_Autofixture - Fatal编程技术网

Unit testing 如何在AutoFixture中更新夹具的自定义

Unit testing 如何在AutoFixture中更新夹具的自定义,unit-testing,autofixture,Unit Testing,Autofixture,在Testbase类中,它像这样定制MyClass fixture.Customize<MyClass>(c => c.Without(r => r.Foo)); 问题是我想在MyClass创建中添加更多自定义项,但似乎最后一个会赢/覆盖第一个,所以它仍然设置MyClass.Foo。 那么,我如何更新自定义而不是覆盖它呢?简单的回答是,您不能这样做。CustomizeAPI总是附加一个新的自定义项,因此前一个自定义项会被覆盖—这是通过设计实现的 作为一种可能的解决方法,

Testbase
类中,它像这样定制
MyClass

fixture.Customize<MyClass>(c => c.Without(r => r.Foo));
问题是我想在
MyClass
创建中添加更多自定义项,但似乎最后一个会赢/覆盖第一个,所以它仍然设置
MyClass.Foo

那么,我如何更新自定义而不是覆盖它呢?

简单的回答是,您不能这样做。
Customize
API总是附加一个新的自定义项,因此前一个自定义项会被覆盖—这是通过设计实现的

作为一种可能的解决方法,您可以使用稍微不同的语法来省略各个属性:

fixture.Customizations.Add(
新省略符(
新EqualRequestSpecification(
typeof(MyClass.GetProperty)(nameof(MyClass.Foo '));
通过这种方式,您可以在以后附加自定义项并扩展例外列表:

fixture.Customizations.Add(
新省略符(
新EqualRequestSpecification(
typeof(MyClass.GetProperty)(nameof(MyClass.Bar()())));

请注意,如果您有继承,这种方法会影响整个类层次结构。因此,如果您省略
BaseClass.Foo
,它也将省略每个子类中的
Foo
属性。

简单的回答是您不能这样做。
Customize
API总是附加一个新的自定义项,因此前一个自定义项会被覆盖—这是通过设计实现的

作为一种可能的解决方法,您可以使用稍微不同的语法来省略各个属性:

fixture.Customizations.Add(
新省略符(
新EqualRequestSpecification(
typeof(MyClass.GetProperty)(nameof(MyClass.Foo '));
通过这种方式,您可以在以后附加自定义项并扩展例外列表:

fixture.Customizations.Add(
新省略符(
新EqualRequestSpecification(
typeof(MyClass.GetProperty)(nameof(MyClass.Bar()())));

请注意,如果您有继承,这种方法会影响整个类层次结构。因此,如果您省略
BaseClass.Foo
,它也将省略每个子类中的
Foo
属性。

这是可能的,但据我所知,您必须编写自己的夹具才能传递到ICCustomization的自定义方法中

我举了一个例子:

我创建了一个名为“Compose()”的扩展方法,它接受ICCustomization。它将一个特殊的装置注入到您定义的自定义类中,并在将它们添加到原始装置的自定义集合之前合并所有自定义

下面是完成大部分工作的代码片段。 设备具有一个自定义集合,其中包含将应用的所有自定义设置。自定义集合是一个列表,据我所知,没有简单的方法知道每个生成器将创建什么类型。因此,在我的新fixture中,我保留字典中的类型信息,并等待调用BuildFixture,然后将实际的定制添加到定制列表中

关键在于定制方法。这是您正在调用的fixture上的方法,用于创建自定义项,因此我们将覆盖它。每次调用时,当前自定义项都会从给定类型的构建器列表中拉出,并在返回到构建器列表之前与新自定义项组合

internal class ComposableCustomizationBuilder : IFixture
{
    private readonly IFixture fixture;

    public ComposableCustomizationBuilder(IFixture fixture)
    {
        this.fixture = fixture;
        this.Builders = new Dictionary<Type, object>();
    }

    // most of the IFixture methods have been removed for brevity since they just return the this.fixture implementation.

    internal Dictionary<Type, object> Builders { get; }

    public IFixture Customize(ICustomization customization)
    {
        customization.Customize(this);
        return this;
    }

    public void Customize<T>(Func<ICustomizationComposer<T>, ISpecimenBuilder> composerTransformation)
    {
        if (!this.Builders.TryGetValue(typeof(T), out object builder))
        {
            var specimenBuilder = composerTransformation(SpecimenBuilderNodeFactory.CreateComposer<T>().WithAutoProperties(true));
            this.Builders.Add(typeof(T), new NodeComposer<T>(specimenBuilder));
            return;
        }

        this.Builders[typeof(T)] = composerTransformation(builder as ICustomizationComposer<T>);
    }

    internal IFixture BuildFixture()
    {
        if (this.fixture is ComposableCustomizationBuilder)
        {
            return this;
        }

        foreach (var builder in this.Builders)
        {
            var specimenBuilder = builder.Value as ISpecimenBuilder;
            this.fixture.Customizations.Add(specimenBuilder);
        }

        return this.fixture;
    }
}
内部类ComposableCustomizationBuilder:IFixture
{
专用只读iTexture夹具;
公共组件定制生成器(IFixture fixture)
{
这个。夹具=夹具;
this.Builders=newdictionary();
}
//为了简洁起见,大多数IFixture方法都被删除了,因为它们只返回this.fixture实现。
内部字典生成器{get;}
公共iTexture自定义(ICustomization自定义)
{
定制。定制(这个);
归还这个;
}
公共void自定义(Func-composer转换)
{
if(!this.Builders.TryGetValue(typeof(T),out object builder))
{
var specimenBuilder=composerTransformation(SpecimenBuilderNodeFactory.CreateComposer().WithAutoProperties(true));
添加(typeof(T),新节点复合器(specimenBuilder));
返回;
}
this.Builders[typeof(T)]=composer转换(builder作为ICustomizationComposer);
}
内部IFixture BuildFixture()
{
if(this.fixture是ComposableCustomizationBuilder)
{
归还这个;
}
foreach(此.Builders中的var builder)
{
var specimenBuilder=builder.Value作为ISpecimenBuilder;
this.fixture.Customizations.Add(specimenBuilder);
}
返回此.fixture;
}
}
使用您的示例,您可以这样编写:

var fixture = new Fixture()
  .Compose<NoBar>()
  .Compose<NoFoo>()
  .Compose();

var result = fixture.Create<MyClass>();

// All the properties should be set as normal by autofixture except for both Foo and Bar which should be omitted.

public class NoBar : ICustomization
{
   public void Customize(IFixture fixture)
   {
      fixture.Customize<MyClass>(c => c.Without(r => r.Bar));
   }
}

public class NoFoo : ICustomization
{
   public void Customize(IFixture fixture)
   {
      fixture.Customize<MyClass>(c => c.Without(r => r.Foo));
   }
}
var fixture=newfixture()
.Compose()
.Compose()
.Compose();
var result=fixture.Create();
//autofixture应将所有属性设置为正常,但应忽略的Foo和Bar除外。
公共类NoBar:ICustomization
{
公共空间自定义(iTexture装置)
{
fixture.Customize(c=>c.Without(r=>r.Bar));
}
}
公共类NoFoo:ICustomization
{
公共空间自定义(iTexture装置)
{
定制(c=>c.Without(r=>r.Foo));
}
}

这是可能的,但据我所知,您必须编写自己的夹具才能传递到ICustomization的定制方法中

我举了一个例子:

我创建了一个名为“Compose()”的扩展方法,它接受ICCustomization。它将一个特殊的装置注入到您定义的自定义类中,并在将它们添加到原始装置的自定义集合之前合并所有自定义

下面是完成大部分工作的代码片段。 设备具有一个自定义集合,其中包含将应用的所有自定义设置。习俗
var fixture = new Fixture()
  .Compose<NoBar>()
  .Compose<NoFoo>()
  .Compose();

var result = fixture.Create<MyClass>();

// All the properties should be set as normal by autofixture except for both Foo and Bar which should be omitted.

public class NoBar : ICustomization
{
   public void Customize(IFixture fixture)
   {
      fixture.Customize<MyClass>(c => c.Without(r => r.Bar));
   }
}

public class NoFoo : ICustomization
{
   public void Customize(IFixture fixture)
   {
      fixture.Customize<MyClass>(c => c.Without(r => r.Foo));
   }
}