【问题标题】:How to validate locals of render template in rspec如何在 rspec 中验证渲染模板的局部变量
【发布时间】:2012-01-12 23:27:12
【问题描述】:

我想知道如何验证在控制器中传递给渲染模板的本地人

控制器:

def lelf_panel
  # ...
  if some_condition
    locals_hash = some_very_long_hash_A
  else
    locals_hash = some_very_long_hash_B
  end
  render :partial => "left_panel", :layout => false, :locals => locals_hash
end

当前规格:

it 'should render correct template for lelf_panel' do
  # ... 
  get 'left_panel'
  response.should render_template('system/_left_panel')
end   

现在我需要完成此控制器的 Rcov,因此我需要添加/修改规范以涵盖两个“some_condition”结果。并且我想验证传递给渲染的“lelf_panel”本地变量,就好像我只验证渲染模板一样,为两个结果渲染的部分页面是相同的。

我在 rspec 文档中检查了“render_template” http://rubydoc.info/gems/rspec-rails/2.8.1/RSpec/Rails/Matchers/RenderTemplate:render_template

它只提供消息的第二个参数,那么我如何测试传递给渲染的本地参数?

【问题讨论】:

    标签: ruby-on-rails rspec rspec-rails


    【解决方案1】:

    您可以在控制器对象上使用期望,而不是使用 render_template 匹配器。

    it 'should render correct template for lefl_panel' do
      # ...
      allow(controller).to receive(:render).with no_args
      expect(controller).to receive(:render).with({
        :partial => 'system/_left_panel',
        :layout  => false,
        :locals  => some_very_long_hash_A
      })
      get 'left_panel'
    end
    

    【讨论】:

    • 这对我有用 - 但只有在我将 get 命令放在 should_receive 评论之后,我还需要添加 controller.stub(:render) 以避免错误 - 但我不确定为什么....
    • 这是最好的答案。更改应用程序以适应测试库的需求是一种代码异味。
    • @Phantomwhale 我刚刚遇到了同样的错误。问题是我们的期望不会渲染或重定向任何东西,所以在动作结束时会调用默认渲染。以前使用 rspec 没问题,但现在是一个未满足的期望。
    • @user94154 的逻辑是正确的——我们的 expect 块从被调用中删除了原来的块,因此调用了默认渲染(没有参数),我们需要另一个 expect/allow 语句来捕捉它。解决这个问题的一个干净的方法是在我们的期望块的末尾添加.and_call_original,这样它不仅会期望它,而且还会继续并在之后调用原始代码。如果您在控制器测试中,请确保您在顶部也启用了render_views,以便实际呈现视图。
    【解决方案2】:

    与@ryan-ahearn 的回答相同,其中包含@user2490003 的评论中的建议 - 但都针对 RSpec 3 进行了更灵活的处理。

      # Safe to set globally, since actions can either render or redirect once or fail anyway
      before do
        allow(controller).to receive(:render).and_call_original
      end
    
      describe "get left panel" do
        before do
          # other setup
          get 'left_panel'
        end
    
        it 'should render correct template for lelf_panel' do
          # Sadly, render_template is primitive (no hash_including, no block with args, etc.)
          expect(subject).to render_template('system/_left_panel')
        end
    
        it 'should render with correct local value' do
          expect(controller).to have_received(:render) do |options|
            expect(options[:locals][:key_from_very_long_hash]).to eq('value_of_key_from_very_long_hash')
          end
        end
      end
    

    【讨论】:

    • 我发现这个是最有用的,但是,我确实必须更改块签名,因为至少在我的 rails 版本(3.2,不要问;)中它传递了名称正在呈现的方法。例如,在我的控制器中,我有 render "index", locals: { presenter: presenter },而在我的规范中,我现在有 expect(controller).to have_received(:render) do |_method, options| .. 其余部分相同。
    【解决方案3】:

    据我所知,没有办法以您描述的方式直接检查本地人的模板。

    您可以将 locals_hash 更改为 @locals_hash,然后通过 assigns(:locals_hash) 检查结果。

    或者,您可以在生成的 HTML 上使用选择器并检查是否存在一些指示性内容 - 例如,如果 locals_hash 影响页面标题,请检查生成的 HTML 页面标题是否符合您的预期。

    【讨论】:

      猜你喜欢
      • 2011-06-28
      • 1970-01-01
      • 2012-04-16
      • 2016-05-22
      • 2016-06-06
      • 2014-10-29
      • 1970-01-01
      • 1970-01-01
      • 2011-06-17
      相关资源
      最近更新 更多