rspec 3.4测试控制器关注response.body.read

时间:2016-06-27 22:38:49

标签: ruby-on-rails ruby rspec

我有以下用于身份验证的控制器问题:

module ValidateEventRequest
  extend ActiveSupport::Concern

  def event_request_verified?(request)
    sha256 = OpenSSL::Digest::SHA256.new
    secret = app_client_id
    body = request.body.read
    signature = OpenSSL::HMAC.hexdigest(sha256, secret, body)
    ([signature] & [request.headers['X-Webhook-Signature'], request.headers['X-Api-Signature']]).present?
  end

  private

  def app_client_id
    ENV['APP_CLIENT_ID']
  end
end

到目前为止,我有以下Rspec测试设置:

RSpec.describe ValidateEventRequest, type: :concern do
  let!(:current_secret) { SecureRandom.hex }

  describe '#event_request_verified?' do
    it 'validates X-Webhook-Signature' do
      # TBD
    end

    it 'validates X-Api-Signature' do
      # TBD
    end
  end
end

我开始时抄袭请求,然后嘲笑和抄袭,现在我要废弃我所拥有的并寻求帮助。 100%的覆盖率对我来说很重要,我正在寻找一些关于如何构建覆盖100%的测试的指针。

2 个答案:

答案 0 :(得分:0)

object_double对测试问题非常方便:

require 'rails_helper'

describe MyClass do
  subject { object_double(Class.new).tap {|c| c.extend MyClass} }

  it "extends the subject" do
    expect(subject.respond_to?(:some_method_in_my_class)).to be true
    # ...

然后你可以像任何其他类一样测试subject。当然,在测试方法时你需要传递适当的参数,这可能意味着创建额外的模拟 - 在你的情况下是一个请求对象。

答案 1 :(得分:0)

以下是我解决这个问题的方法,我对这些想法持开放态度:

RSpec.describe ValidateApiRequest, type: :concern do
  let!(:auth_secret) { ENV['APP_CLIENT_ID'] }
  let!(:auth_sha256) { OpenSSL::Digest::SHA256.new }
  let!(:auth_body) { 'TESTME' }
  let(:object) { FakeController.new }
  before(:each) do
    allow(described_class).to receive(:secret).and_return(auth_secret)
    class FakeController < ApplicationController
      include ValidateApiRequest
    end
  end

  after(:each) do
    Object.send :remove_const, :FakeController
  end

  describe '#event_request_verified?' do
    context 'X-Api-Signature' do
      it 'pass' do
        request = OpenStruct.new(headers: { 'X-Api-Signature' => OpenSSL::HMAC.hexdigest(auth_sha256, auth_secret, auth_body) }, raw_post: auth_body)
        expect(object.event_request_verified?(request)).to be_truthy
      end

      it 'fail' do
        request = OpenStruct.new(headers: { 'X-Api-Signature' => OpenSSL::HMAC.hexdigest(auth_sha256, 'not-the-same', auth_body) }, raw_post: auth_body)
        expect(object.event_request_verified?(request)).to be_falsey
      end
    end

    context 'X-Webhook-Signature' do
      it 'pass' do
        request = OpenStruct.new(headers: { 'X-Webhook-Signature' => OpenSSL::HMAC.hexdigest(auth_sha256, auth_secret, auth_body) }, raw_post: auth_body)
        expect(object.event_request_verified?(request)).to be_truthy
      end

      it 'fail' do
        request = OpenStruct.new(headers: { 'X-Webhook-Signature' => OpenSSL::HMAC.hexdigest(auth_sha256, 'not-the-same', auth_body) }, raw_post: auth_body)
        expect(object.event_request_verified?(request)).to be_falsey
      end
    end
  end
end