Ruby on rails 用类扩展控制器
创建自定义匹配器以测试某些局部变量:Ruby on rails 用类扩展控制器,ruby-on-rails,rspec,Ruby On Rails,Rspec,创建自定义匹配器以测试某些局部变量: RSpec::Matchers.define :set_the_local_variable do |variable| match do |actual| @actual = controller.binding.local_variable_get(variable) @actual == @expected end failure_message do |actual|
RSpec::Matchers.define :set_the_local_variable do |variable|
match do |actual|
@actual = controller.binding.local_variable_get(variable)
@actual == @expected
end
failure_message do |actual|
"set '#{@actual}' equal to #{@expected}. However, it did not: \n '#{@actual.inspect}' \n '#{@expected.inspect}'"
end
failure_message_when_negated do |actual|
"set '#{@actual}' not equal to #{@expected}. However, it did: \n '#{@actual.inspect}' \n '#{@expected.inspect}'"
end
description do
"set the instance '#{@actual}' to equal '#{expected}'"
end
def to(expected)
@expected = expected
self
end
end
但是,这一行:
controller.binding.local_variable_get(variable)
给我这个错误:
private method `binding' called for #<StaticController:0x00000104b5a108>
有人能解释一下这是怎么回事吗?我了解类、实例、继承和私有类方法,但我不知道如何使其工作
我想找出包含绑定的类,并在匹配块中用该类扩展控制器?类似的东西?绑定的文档说明: 返回一个绑定对象,描述变量和方法绑定 在通话的时候 (增加重点) 在IRB中试试这个:
> self
main
> binding
=> #<Binding:0x007fa89a8be670>
> self.binding
NoMethodError: private method `binding' called for main:Object
>self
主要的
>装订
=> #
>自绑定
NoMethodError:为main:对象调用了私有方法“binding”
当然,您可以直接发送消息:
> self.send(:binding)
=> #<Binding:0x007fa89a890b30>
>self.send(:绑定)
=> #
但这与键入绑定
是一样的
您在IRB中键入的内容是在顶级main
方法的上下文中完成的。当您执行controller.binding
时,您正在调用RSpec为您创建的测试控制器实例上的方法。但是,上下文是RSpec示例实例,而不是控制器实例,这(可能?)不是您想要的
实际上,尽管这都是学术性的:在测试时,深入实例并检查局部变量的值是不明智的。如果您很想这样做,这表明需要进行一些重构。为什么要测试局部变量?使您无法重构脆弱的测试和代码。测试副作用,如创建的实例变量
赋值(:inst\u variable\u name\u here)
或重定向,它们在控制器规范中已经有匹配器。我知道,我不是在测试每个变量(心理),只是测试我真正想测试的一个散列。你能将其提取到服务对象中并在那里进行单元测试吗?我下意识的反应是,你实际上是在蒙骗rspec,而不是在正确的水平上测试你想要完成的事情。不管怎样,祝你好运。我认为你是对的,虽然我可以让它成为助手,但我只在一个地方使用它。这不是什么大问题。如果我得到答案,我会看看会发生什么:)是的,我明白了。这根本不是问题,但我有点好奇如何进行局部变量测试。如何将binding.local\u variable\u get()
发送到控制器?这,controller.send(:binding).send(:local_variables)
返回实际匹配器中的局部变量(actual
和variable
),我不知道rspec创建了控制器的另一个实例。为什么控制器中的局部变量不会出现在rspec实例中?rspec不会创建单独的控制器实例,如果我在这一点上混淆了,很抱歉。我试图得到的是调用controller.send(:binding)
会返回与在示例上下文中调用binding
相同的上下文,这与在matcher中调用它时看到的效果相同。这似乎违反直觉,但它是有意义的,因为Binding
将上下文封装在调用它的位置,而不是接收器中的某个位置。例如,尝试controller.send(:binding.eval('controller')
——返回相同的实例,对吗?
> self.send(:binding)
=> #<Binding:0x007fa89a890b30>