Как мне макетировать параметры с помощью Machine.Fakes независимо от макета фреймворка?

Я зашел в тупик с Machine.Fakes. Я не могу понять, как издеваться над out параметр, использующий только оборудование Machine.Fakes. Из-за ошибки в RhinoMocks я переключил наш адаптер mfakes на FakeItEasy. Насколько я могу судить, любой из адаптеров должен быть взаимозаменяемым.

Проблема заключается в том, что это привело к сбою "вне" тестов, вещи, которые выглядели так, больше не компилируются, потому что Arg был Rhino.Mocks.

The<IMembershipService>()
    .WhenToldTo(x => x.CreateUser(Param<string>.IsAnything,
        Param<bool>.IsAnything,
        Param<object>.IsAnything, 
        out Arg<MembershipCreateStatus>
            .Out(MembershipCreateStatus.UserRejected)
            .Dummy))
    .Return(user);

Я попытался использовать "фиктивную" локальную переменную, установив на то же значение оригинал Arg<T> для параметра установлено значение, но это привело к сбою моих тестов - кажется, что значение не передается! Arg<T> действительно было решение, но я больше не могу его использовать, так как это часть Rhino.Mocks.

3 ответа

Решение

Начиная с версии 1.7.0 Machine.Fakes поддерживает настройку out а также ref параметры в ложных вызовах - при использовании адаптеров FakeItEasy или NSubstitute. Таким образом, вам больше не нужно использовать FakeItEasy напрямую. Пример Алекса можно упростить так:

using Machine.Fakes;
using Machine.Specifications;

namespace MSpecMFakesOutParam
{
    public interface IFoo
    {
        void Foo(out int foo);
    }

    public class When_using_FakeItEasy_with_out_params : WithFakes
    {
        static int Out;

        Establish context = () =>
        {
            int ignored;
            The<IFoo>().WhenToldTo(x => x.Foo(out ignored)).AssignOutAndRefParameters(42);
        };

        Because of = () => The<IFoo>().Foo(out Out);

        It should_assign_the_out_param = () => Out.ShouldEqual(42);
    }
}

Machine.Fakes не справляется с этим сценарием. Это просто не реализовано.

Лично я не использую параметры и (если мне действительно нужно вернуть несколько возвращаемых значений) использую кортеж (Tuple) или пользовательский класс для таких сценариев. Вот почему это никогда не было действительно высоким приоритетом.

Я не рассматривал это, но возможно, что реализация обработки параметров ref и out в Machine.Fakes неосуществима. Одна из проблем реализации оболочки поверх нескольких фальшивых фреймворков заключается в том, что для достижения успеха все фальшивые фреймворки должны иметь общий знаменатель того, как они работают. Machine.Fakes также не поддерживает насмешливые события сейчас, потому что я не смог найти общий знаменатель для всех них (только для двух NSubstitute/FakeItEasy против Rhino/Moq).

На мой взгляд, у вас есть два варианта:

  1. Если вы контролируете интерфейс, о котором мы говорим, вы можете обойти проблему с помощью кортежа или пользовательского класса.
  2. Если у вас нет интерфейса, вы всегда можете вернуться к базовому макету для таких случаев, как предложил Александр Гросс.

Извините, что не дал вам лучшего ответа;-)

  • Бьорн

Похоже, что для этого случая вам нужно использовать FakeItEasy напрямую. Я думаю, что проблема заключается в том, как FakeItEasy требует от вас настройки out параметры путем добавления AssignsOutAndRefParameters к спецификации вызова поддельного объекта. Это не должно быть проблемой, поскольку все, что делает Machine.Fakes - это перевод WhenToldTo и т.д. к соответствующему API используемой фальшивой структуры.

using FakeItEasy;

using Machine.Fakes;
using Machine.Specifications;

namespace MSpecMFakesOutParam
{
  public interface IFoo
  {
    void Foo(out int foo);
  }

  public class When_using_FakeItEasy_with_out_params : WithFakes
  {
    static IFoo Foo;
    static int Out;

    Establish context = () =>
    {
      Foo = An<IFoo>();

      var ignored = A<int>.Ignored;
      A.CallTo(() => Foo.Foo(out ignored)).AssignsOutAndRefParameters(42);
    };

    Because of = () => Foo.Foo(out Out);

    It should_assign_the_out_param =
      () => Out.ShouldEqual(42);
  }
}
Другие вопросы по тегам