我有一个页面dashboard.html.erb
,可以从几个不同的控制器/操作重定向到该页面。当它接收到重定向时,它还接收到几个url参数。
控制器代码:
class PlansController
def some_action
redirect_to dashboard_path(show: "default", cool_array: ["test", "test"])
end
end
class StaticpagesController
def dashboard
end
end
查看代码:
<% if cool_array %>
<% cool_array.each do |a| %>
<li><%= a %></li>
<% end %>
<% end %>
<script>
var show = getParamFromURL("show")
// some sort of function that returns the value of the show param, in this case, "default"
if (show == "default") {
$("#default").addClass("show");
} else {
$("#other").addClass("hidden");
}
</script>
因为这些都是重定向,所以使用render_views
进行控制器测试将不起作用。因此,我曾想过构建我的测试,以便控制器规范测试是否传递了正确的参数,视图规范测试是否存在某些参数,是否存在正确的css类,或者其他什么。但在我的视图规范中,我在模拟参数传递时遇到了问题。
这似乎是我发现的唯一其他问题:RSpec视图测试:如何修改参数?
但这些解决方案对我都不起作用;我不确定在这种情况下我需要一个帮手。。。这似乎有点做作。。。
我尝试过(从上面链接的SO问题):
before do
controller.request.path_parameters[:cool_array] = ["test","test"]
end
# => ActionView::Template::Error:
# undefined local variable or method `cool_array' for #<#<Class:0x007fe2d9815100>:0x007fe2d90a62e8>
# thrown by line in view file with <% if cool_array %>
before do
view.stub(:params).and_return({cool_array: ["test", "test"]})
end
# => ActionView::Template::Error:
# undefined local variable or method `cool_array' for #<#<Class:0x007fe2d9815100>:0x007fe2d90a62e8>
# thrown by line in view file with <% if cool_array %>
helper.params = {:cool_array => ["test", "test"]]}
# honestly not even sure this is right, because it can only go into a describe block (not a before, not an it) and then it throws:
# NoMethodError:
# undefined method `params=' for #<#<Class:0x007fd7cc8f4930>:0x007fd7cc8a5060>
它们都失败了:
因为这些都是重定向,所以使用render_views进行控制器测试将不起作用。
不,你只是做错了。
如果StaticpagesController#dashboard
接受url参数,您应该测试它如何响应StaticpagesController的控制器规范中的所述参数。
RSpec.describe StaticpagesController, type: :controller do
describe 'GET #dashboard' do
render_views
it "does something with the x parameter" do
get :dashboard, x: 'hello!'
expect(response.body).to match 'hello!'
end
end
end
同样,您应该测试PlansController#some_action是否在响应中包含正确的参数。
我认为您的视图规范问题告诉您,您的视图中有代码气味。在MVC中,控制器负责接收输入并将其传递给视图和模型。将您的视图与直接处理参数隔离意味着处理它的参数不会在整个应用程序中重复。
在控制器中使用locals
将变量传递到视图,并避免在视图中使用params
。
它有助于更好的设计和更容易的测试:
describe "rendering locals in a partial" do
it "displays the widget" do
widget = stub_model(Widget, :name => "slicer")
render :partial => "widgets/widget.html.erb", :locals => {:widget => widget}
rendered.should contain("slicer")
end
end