2

I've hit an impasse with Machine.Fakes. I cannot figure out how to mock an out parameter using only Machine.Fakes equipment. Because of a bug in RhinoMocks, I switched our mfakes adapter to FakeItEasy. As far as I can tell, any of the adapters should be interchangable.

The problem is that this caused the "out" tests to fail, things that looked like this no longer compile, because Arg was 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);

I tried using a "dummy" local variable, set to the same value the original Arg<T> param set it to, but this has caused my tests to fail -- it seems as though the value isn't being passed through! Arg<T> really had the solution, but I can't use it anymore, as it's part of Rhino.Mocks.

4

3 回答 3

7

Machine.Fakes 不处理这种情况。它根本没有实施。

我个人不使用 out 参数,并且(如果我真的需要返回多个返回值)在这种情况下使用元组 (Tuple<T,K>) 或自定义类。这就是为什么它从来没有真正放在我的优先级上。

我还没有研究过,但是在 Machine.Fakes 中实现对 ref 和 out 参数的处理可能是不可行的。在多个模拟框架之上实现包装器的挑战之一是,为了成功,所有模拟框架都需要在工作方式上有一个共同点。Machine.Fakes 现在也不支持模拟事件,因为我无法找到所有这些事件的共同点(仅适用于两个 NSubstitute/FakeItEasy 与 Rhino/Moq)。

如我所见,您目前有两种选择:

  1. 如果您控制我们正在谈论的接口,则可以通过元组或自定义类绕过该问题。
  2. 如果您不拥有该界面,您可以随时恢复到 Alexander Gross 建议的情况下的底层模拟框架。

很抱歉没有给你更好的答案;-)

  • 比约恩
于 2012-01-04T20:28:24.753 回答
5

对于这种情况,您似乎需要直接使用 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);
  }
}
于 2012-01-04T13:14:03.733 回答
1

从 1.7.0 版开始,Machine.Fakes 支持在假调用中设置outref参数 - 当使用 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);
    }
}
于 2013-08-02T11:37:09.270 回答