如何将带有存根方法的对象在 it_behaves_like 中传递给 rspec 中的 shared_examples_for 块? [英] How to pass objects with stubbed methods in it_behaves_like to shared_examples_for block in rspec?

查看:28
本文介绍了如何将带有存根方法的对象在 it_behaves_like 中传递给 rspec 中的 shared_examples_for 块?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个规范

describe MyClass do
  it_behaves_like SharedClass, MyClass.new
end

在我的共享示例规范中,我有

and in my shared example spec, I have

shared_examples_for SharedClass do |instance|
  before do 
    instance.some_my_class_method = double
  end
  # some specs here
end

MyClass 实例中有几个方法我不能在 shared_examples_for 块中存根,所以我想在将它们传递到 it_behaves_like 语句之前存根它们.喜欢,

There are few methods in MyClass instance that I cannot stub in the shared_examples_for block, so I want to stub them before passing it in it_behaves_like statement. like,

describe MyClass do
  before do
    @instance = MyClass.new
    @instance.stub(:my_class_method)
  end
  it_behaves_like SharedClass, @instance
end

但我不能那样做.它让我很失望
无方法错误:未定义的方法 `some_my_class_method=' for nil:NilClass

but I cannot do that.It throws me
NoMethodError: undefined method `some_my_class_method=' for nil:NilClass

不知何故,我无法在 shared_examples_for 上下文中访问该 @instance 对象.我正在使用 ruby​​ 1.9.3p392 和 rspec (2.14.1)

somehow I am not able to access that @instance object in the shared_examples_for context. I am using ruby 1.9.3p392 and rspec (2.14.1)

推荐答案

问题是您传递给 it_behaves_like 的参数在调用 it_behaves_like 时被评估,而 before 块在共享示例执行之前被评估,这发生在稍后的时间.结果,作为参数的 @instance 被评估为 nil 并且形参 instance 被赋值为 nil,导致您的 undefined method 错误.

The problem is that the arguments you pass to it_behaves_like are evaluated at the time it_behaves_like is called, while the before block is evaluated just before the shared example is executed, which occurs at a later time. As a result, @instance as an argument is evaluated to nil and the formal parameter instance is assigned nil, resulting in your undefined method error.

我不知道有什么简单的方法可以完成您想要完成的任务.这个文档是为了消除形参,并要求调用者传递一个使用let来建立参数值的块,使用一些约定好的变量,如下:

I don't know of any easy way to do what you're trying to accomplish. One alternative shown in this documentation is to eliminate the formal parameter and require the caller to pass a block which uses let to establish the argument value, using some agreed to variable, as follows:

describe MyClass do
  it_behaves_like SharedClass {let(:instance) { MyClass.new }}
end

describe MyClass do
  it_behaves_like SharedClass do
    let(:instance) do
      myClass = MyClass.new
      myClass.stub(:my_class_method)
      myClass
    end
  end
end

然而,除了更加冗长之外,这还有一个缺点,即在您的共享示例中没有隐式文档,它期望 instance 在调用时设置.

In addition to being more verbose, however, this has the disadvantage that there is no implicit documentation within your shared example that it expects instance to set when it's called.

虽然我没有在任何地方看到它讨论过,但是当且仅当形参的值为 nil,为方便起见可以默认.不幸的是,您不能对两者使用相同的变量,因为参数的值将始终优先.

Although I've not seen it discussed anywhere, a somewhat hacky alternative would be have your shared example use the agreed-to-variable from the block if and only if the value of the formal parameter is nil, which could be defaulted for convenience. Unfortunately, you can't use the same variable for both, as the value of the parameter will always take precedence.

这篇关于如何将带有存根方法的对象在 it_behaves_like 中传递给 rspec 中的 shared_examples_for 块?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆