如何使用Machine.Fakes模拟'out'参数独立于模拟框架?

时间:2012-01-04 00:03:22

标签: c# unit-testing mocking rhino-mocks machine.fakes

我遇到了Machine.Fakes的僵局。我无法弄清楚如何使用 only Machine.Fakes设备模拟out参数。由于RhinoMocks中的a bug,我将我们的mfakes适配器切换为FakeItEasy。据我所知,任何适配器都应该是可互换的。

问题是这导致“out”测试失败,看起来像这样的东西不再编译,因为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> param设置的相同值,但这导致我的测试失败 - 似乎值不是通过传递! Arg<T>确实有解决方案,但我不能再使用它了,因为它是Rhino.Mocks的一部分。

3 个答案:

答案 0 :(得分:7)

Machine.Fakes无法处理此方案。它根本没有实现。

我个人不使用out参数和(如果我真的需要返回多个返回值)使用元组(Tuple&lt; T,K&gt;)或自定义类来表示这种情况。这就是为什么我的优先权从未如此高。

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

我认为你目前有两种选择:

  1. 如果您控制我们正在讨论的界面,您可以通过元组或自定义类来绕过问题。
  2. 如果您不拥有该界面,您可以随时恢复到基础模拟框架,以满足Alexander Gross建议的情况。
  3. 很抱歉没有给你更好的答案; - )

    • 比约恩

答案 1 :(得分: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);
  }
}

答案 2 :(得分: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);
    }
}