【问题标题】:Rspec for testing the rendered template outside of controller/view用于在控制器/视图之外测试渲染模板的 Rspec
【发布时间】:2018-12-05 18:09:56
【问题描述】:

我有一种情况要在控制器之外渲染一个 HTML 模板(service/lib 目录下的一个类),我正在使用下面的代码渲染模板。

class SomeClass
   def some_method
      @template = ApplicationController.render(
            template: 'template',
            layout: mailer_template,
        )
   end
end

有什么方法可以测试渲染的模板是否是预期的模板,以及在该方法调用期间是否发生了渲染?

编辑

class BatchSendingService < AbstractController::Base

    require 'abstract_controller'

    include AbstractController::Rendering
    include AbstractController::AssetPaths
    include AbstractController::Helpers
    include Rails.application.routes.url_helpers


    include ActionView::Rendering
    include ActionView::ViewPaths
    include ActionView::Layouts
    self.view_paths = "app/views"

    def send_batch_email(mail, domain)
       @project = mail.project
       @client = Mailgun::Client.new ENV['MAILGUN_API_KEY']
       batch_message = Mailgun::BatchMessage.new(@client, domain)
       batch_message.from(from_data)

       mailer_layout = get_mailer_layout(mail.layout)
       mail_html = render(
          template: 'send_batch_email',
          layout: mailer_layout
      )

       batch_message.body_html(mail_html.to_s)

      batch_message.add_recipient(:to, recipient_email, {})
      response = batch_message.finalize 
   end

编辑

obj= BatchSendingService.new allow(obj).to receive(:render) BatchSendingService.send_batch_email(mail, domain) expect(obj) .to have_received(:render) .with({ template: "template", layout: "layout" })

通过使用调用实例方法的类,错误消失了。

【问题讨论】:

  • 正在渲染的布局/模板中有太多本地和其他样式。因此,如果我能够检查调用方法是否呈现了布局,那就太好了。您能解释一下如何使用邮件规范进行测试吗?仅供参考:此方法发送批量发送 API。

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


【解决方案1】:

ActionController.render 是一个经过良好测试的方法。 Rails 核心团队看到了这一点。无需测试它是否按照它所说的那样做。

相反,您要做的是确保使用正确的参数调用ActionController.render,使用模拟对象,如下所示:

describe SomeClass do
  subject(:some_class) { described_class.new }

  describe '#some_method' do
    let(:template) { 'template' }
    let(:layout) { 'mailer_template' }

    before do
      allow(ActionController).to receive(:render)

      some_class.some_method
    end

    it 'renders the correct template' do
      expect(ActionController)
        .to have_received(:render)
        .with({ template: template, layout: layout })
    end
  end
end

编辑

鉴于已编辑的帖子,这就是我将如何进行测试。请注意,并非send_batch_email 方法中的所有代码都在您的编辑中可见。所以,YMMV:

describe BatchSendingService do
  subject(:batch_sending_service) { described_class.new }

  describe '#send_batch_email' do
    subject(:send_batch_email) do 
      batch_sending_service.send_batch_email(email, domain)
    end

    let(:email) { 'email' }
    let(:domain) { 'domain' }
    let(:batch_message) do
      instance_double(
        Mailgun::BatchMessage, 
        from: true,
        body_html: true,
        add_recipient, true,
        finalize: true
      )
    end
    let(:template) { 'send_batch_template' }
    let(:layout) { 'layout' }

    before do
      allow(Mailgun::Client).to receive(:new)
      allow(Mailgun::BatchMessage)
        .to receive(:new)
        .and_return(batch_message)
      allow(batch_sending_service)
        .to receive(:render)

      send_batch_email
    end

    it 'renders the correct template' do
      expect(batch_sending_service)
        .to have_received(:render)
        .with(template, layout)
    end
  end
end

【讨论】:

  • 收到类似RSpec::Mocks::MockExpectationError: #&lt;ActionController::Base:0x007fb9698b6f30 @_action_has_layout=true, @_routes=nil, @_request=nil, @_response=nil&gt; expected to have received render, but that object is not a spy or method has not been stubbed的错误
  • allow(ActionController).to receive(:render) 设置该模拟。请注意,它是在模拟 ActionController 而不是 ActionController::Base。如果被测类实际调用ActionController::Base,则需要模拟该类。请随时在您的问题中发布更完整的代码示例,我会再看一下。
  • 看起来消息.render 正在发送到BatchSendingService 类。在我上面的答案中用BatchSendingService 代替ApplicationController 应该可以解决问题。
  • 是的,错误消失了,但是好像没有调用render方法(#&lt;BatchSendingService:0x007fba59b1fe70 @_action_has_layout=true, @_routes=nil&gt;).render({:template=&gt;"template", :layout=&gt;"layout"}) expected: 1 time with arguments: ({:template=&gt;"template", :layout=&gt;"layout"}) received: 0 times
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多