c# remove - Невозможно понять разницу между Freeze / Inject / Register




html tags (4)

Регистрация и ввод

Когда-то давно не было Inject и не было Freeze ; Register управлял кодом.

Тогда была Register перегрузка Register :

public static void Register<T>(this IFixture fixture, T item)

Однако ему пришлось делиться API с этим близким родственником:

public static void Register<T>(this IFixture fixture, Func<T> creator)

Создатель AutoFixture думал, что это хорошо, но, увы: пользователи были поражены путаницей. Самый печально, пользователь мог написать:

fixture.Register(() => universe.LightUp());

но также

fixture.Register(universe.LightUp);

что означает то же самое, потому что universe.LightUp является ссылкой на метод и, таким образом, соответствует делегату.

Однако этот синтаксис выглядит как ссылка на свойство, поэтому, если LightUp был свойством вместо метода, первая перегрузка будет выбрана компилятором.

Это вызвало много путаницы, поэтому перегрузка Register<T>(this IFixture fixture, T item) была переименована в Inject<T>(this IFixture fixture, T item) .

замерзать

У замораживания есть другая история. Давным-давно, когда я все еще использовал AutoFixture в императивном ключе, я заметил, что я неоднократно писал код следующим образом:

var foo = fixture.Create<Foo>();
fixture.Inject(foo);

Поэтому я решил, что это была концепция и назвала ее Freeze . Метод Freeze - это только сокращение для этих двух строк кода.

Я ищу вашу помощь, чтобы понять разницу между Freeze, Inject, а также Register, который, согласно исходному коду, просто вызывается методом Inject, но требует лямбда

В общем, не должно быть слишком сложно различать Inject и Register , поскольку их подписи не сталкиваются. Таким образом, если вы попытаетесь достичь цели одним из этих двух методов, и ваш код компилируется, вы, вероятно, выбрали правильную версию.

Это также будет иметь место для Freeze если бы не перегрузка, используемая в OP:

[EditorBrowsable(EditorBrowsableState.Never)]
public static T Freeze<T>(this IFixture fixture, T seed)

Обратите внимание, что эта перегрузка на самом деле имеет EditorBrowsableState.Never , потому что она всегда путает людей. Однако, несмотря на это, очевидно, люди все еще находят эту перегрузку, поэтому я думаю, что ее нужно перенести в AutoFixture 4 . Это одна из тех функций, которые существуют, потому что их было легко реализовать ...

Прежде чем начать, я большой поклонник AutoFixture, я все еще нахожусь в основе изучения того, как использовать инструмент. Так что спасибо за разработку Autofixture Mr Ploeh и всех участников.

Давайте начнем с моего вопроса.

В соответствии с AutoFixture / AutoMoq игнорируется инъецированный экземпляр / замороженный макет

Интересная часть приведенной ссылки приведена в этом коде

Mock<ISettings> settingsMock = new Mock<ISettings>();
settingsMock.Setup(s => s.Get(settingKey)).Returns(xmlString);

ISettings settings = settingsMock.Object;
fixture.Inject(settings);

На что Марк отвечает, он может быть переписан

fixture.Freeze<Mock<ISettings>>()
       .Setup(s => s.Get(settingKey)).Returns(xmlString);

Он выглядит как синтаксический сахар, используя метод замораживания - это способ свободно писать интерфейс, создавая макет, конфигурацию и инъекцию в контейнере для автохимии.

После некоторых исследований в Интернете на самом деле существует функциональное различие между Freeze и Inject. Я нашел этот вопрос: https://github.com/AutoFixture/AutoFixture/issues/59 котором указывается ответ на вопрос, как я могу заморозить нулевой экземпляр в AutoFixture

Автор ссылки выше описывает метод Freeze следующим образом:

Внутри Freeze создает экземпляр запрошенного типа (например, IPayPalConfiguration), а затем вводит его, чтобы он всегда возвращал этот экземпляр, когда вы запрашиваете его снова

Я понимаю, что когда мы это делаем

var customer = fixture.Freeze<Order>();

он всегда будет использовать тот же экземпляр Order, когда наш код запрашивает тип Order. Но что, если я укажу в конструкторе Freeze, что я хочу, чтобы он использовал конкретный экземпляр?

Вот пример небольшого кода:

[Fact]
public void MethodeName()
{
    var fixture = new Fixture().Customize(new AutoMoqCustomization());
    fixture.Freeze<OrderLine>(new OrderLine("Foo"));
    var order = fixture.Create<Order>();
}

public class Order
{
    private readonly OrderLine _line;

    public Order(OrderLine line)
    {
        _line = line;
    }
}
public class OrderLine
{
    private readonly string _name;

    public OrderLine(string name)
    {
        _name = name;
    }
}

Должно ли имя OrderLine быть равно «Foo» вместо namefe48163a-d5a0-49a5-b349-7b11ba5f804b? В документации по методу замораживания говорится:

<typeparam name="T">The type to freeze.</typeparam>
<param name="fixture">The fixture.</param>
<param name="seed">Any data that adds additional information when creating the anonymous object. Hypothetically, this value might be the value being frozen, but this is not likely.</param>

почему автор не уверен, когда возвращается значение? Если я укажу, мой экземпляр в конструкторе Freeze, я ожидаю, что autofixture будет использовать этот экземпляр?

тогда

Обратите внимание, что это вряд ли будет использоваться в качестве замороженного значения, если вы не настроили его. Если вы хотите ввести определенное значение в Fixture, вы должны использовать этот метод вместо этого. `

Кажется, я должен настроить параметр seed. Может ли кто-нибудь уточнить? Решение, указанное в документации, заключается в использовании метода Inject. И действительно, он работает в моем примере кода с OrderLine.

Я ищу вашу помощь, чтобы понять разницу между Freeze, Inject, а также Register, который, согласно исходному коду, просто вызывается методом Inject, но он принимает lambda.


Я изменил ваш тест (который ничего не утверждает в настоящее время, BTW), и если вы выполните его выполнение, вы увидите OrderLine с «Foo», поскольку его личное значение члена _line вводится в Order .

У меня была другая версия теста, в которой я добавил свойства readonly для OrderLine в Order и Name в OrderLine чтобы вы могли делать утверждения об этих объектах, но это ни здесь, ни там.

Этот тест устанавливает прибор непосредственно с FromFactory метода FromFactory , что может быть полезно иногда:

[Fact]
public void MethodName()
{
    var fixture = new Fixture().Customize(new AutoMoqCustomization());
    const string expected = "Foo";
    fixture.Customize<OrderLine>(o => o
        .FromFactory(() =>
            new OrderLine(expected)));
    var order = fixture.Create<Order>();
}

Freeze , Inject и Register все настраивают алгоритм создания.

С помощью Inject и Register вы явно указываете, что объект должен быть создан определенным образом, в вашем примере, предоставляя new OrderLine("Foo") вручную.

С помощью Freeze вы не указываете, как должен быть создан объект - вы попросите AutoFixture предоставить вам экземпляр.

В итоге все вышеперечисленные методы используют один и тот же API нижнего уровня:

fixture.Customize<T>(c => c.FromFactory(creator).OmitAutoProperties());

Причина, почему fixture.Freeze<OrderLine>(new OrderLine("Foo")); не создает экземпляр OrderLine с указанным начальным значением, потому что по умолчанию семя игнорируется .

Чтобы поддержать значения семян определенного типа, вы можете создать SeedFavoringRelay<T> :

public class SeedFavoringRelay<T> : ISpecimenBuilder where T : class
{
    public object Create(object request, ISpecimenContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");

        var seededRequest = request as SeededRequest;
        if (seededRequest == null || !seededRequest.Request.Equals(typeof(T)))
            return new NoSpecimen(request);

        var seed = seededRequest.Seed as T;
        if (seed == null)
            return new NoSpecimen(request);

        return seed;
    }
}

Затем вы можете использовать его, как показано ниже:

fixture.Customizations.Add(
    new SeedFavoringRelay<OrderLine>());

fixture.Freeze<OrderLine>(new OrderLine("Foo"));
// -> Now fixture.Create<Order>() creates an Order with OrderLine's Name = "Foo".

Вы можете использовать следующий код:

 int DateDifInSecond = EndDate.Subtract(StartDate).TotalSeconds






c# autofixture