ruby-on-rails - rspec 在需要 stub 的私有(private)方法中测试私有(private)方法

标签 ruby-on-rails rspec tdd simplecov

Simplecov 检测到我缺少对 lib/api_verson.rb 类的一些测试:

class ApiVersion

  def initialize(version)
    @version = version
  end

  def matches?(request)
    versioned_accept_header?(request) || version_one?(request)
  end

  private

  def versioned_accept_header?(request)
    accept = request.headers['Accept']
    accept && accept[/application\/vnd\.#{Rails.application.secrets.my_app_accept_header}-v#{@version}\+json/]
  end

  def unversioned_accept_header?(request)
    accept = request.headers['Accept']
    accept.blank? || accept[/application\/vnd\.#{Rails.application.secrets.my_app_accept_header}/].nil?
  end

  def version_one?(request)
    @version == Rails.application.secrets.my_app_default_api_version && unversioned_accept_header?(request)
  end

end

路由文件使用此类来帮助设置 api 版本:

namespace :api, path: "", defaults: {format: :json} do

scope module: :v1, constraints: ApiVersion.new(1) do
  get '/alive', to: 'api#alive'
end

scope module: :v2, constraints: ApiVersion.new(2) do
  get '/alive', to: 'api#alive'
end

end

此设置移植自 versioning_your_ap_is .

我正在尝试测试 simplecov 报告为失败的方法,现在我陷入了私有(private)方法包含私有(private)方法的情况......

  def version_one?(request)
    @version == Rails.application.secrets.my_app_default_api_version && unversioned_accept_header?(request)
  end

这是我当前的规范:

require 'spec_helper'

describe ApiVersion do

  before(:each) do
    @apiversion = ApiVersion.new(1)
    @current_api_version = Rails.application.secrets.my_app_default_api_version
    @request = ActionController::TestRequest.new(host: 'localhost')
    @request.headers["Accept"] = "application/vnd.#{Rails.application.secrets.my_app_accept_header}-v#{@current_api_version}+json"
  end

  describe "Method #versioned_accept_header? =>" do
    it "Should return false if the header accept variable contains application/vnd.#{Rails.application.secrets.my_app_accept_header}-v#{@current_api_version}+json" do
      expect(@apiversion.send(:unversioned_accept_header?, @request)).to eq(false)
    end
    it "Should return true if no version is included with the header" do
      request = @request
      request.headers["Accept"] = nil
      expect(@apiversion.send(:unversioned_accept_header?, request)).to eq(true)
    end
  end

  describe "Method #version_one? =>" do
    it "test me" do
      # @apiversion.send(:unversioned_accept_header?, @request)

      binding.pry

      # expect(@apiversion.send(:version_one?, @request)).to eq(false)
    end
  end

end

如何 stub 嵌套私有(private)方法来测试 version_one 私有(private)方法?

最佳答案

以下是我最终测试和覆盖率达到 100% 的结果。

lib/api_version.rb 文件:

class ApiVersion

  def initialize(version)
    @version = version
  end

  def matches?(request)
    versioned_accept_header?(request) || version_default?(request)
  end

  private

  def versioned_accept_header?(request)
    accept = request.headers['Accept']
    accept && accept[/application\/vnd\.#{Rails.application.secrets.my_app_accept_header}-v#{@version}\+json/]
  end

  def unversioned_accept_header?(request)
    accept = request.headers['Accept']
    accept.blank? || accept[/application\/vnd\.#{Rails.application.secrets.my_app_accept_header}/].nil?
  end

  def version_default?(request)
    @version == Rails.application.secrets.my_app_default_api_version && unversioned_accept_header?(request)
  end

end

接下来是所有 rspec 测试:

require 'spec_helper'

describe ApiVersion do

  before(:each) do
    @apiversion = ApiVersion.new(1)
    @current_api_version = Rails.application.secrets.my_app_default_api_version
    @request = ActionController::TestRequest.new(host: 'localhost')
  end

  describe "Method #matches? =>" do
    it "Should return false when the header is not versioned and it's not the header default." do
      @apiversion.stub(:versioned_accept_header?).and_return(false)
      @apiversion.stub(:version_default?).and_return(false)
      expect(@apiversion.matches?(@request)).to eq(false)
    end
    it "Should return true when the proper header has been supplied but is unversioned." do
      @apiversion.stub(:versioned_accept_header?).and_return(true)
      @apiversion.stub(:version_default?).and_return(false)
      expect(@apiversion.matches?(@request)).to eq(true)
    end
    it "Should return true when the proper header has been supplied and is versioned." do
      @apiversion.stub(:versioned_accept_header?).and_return(true)
      @apiversion.stub(:version_default?).and_return(true)
      expect(@apiversion.matches?(@request)).to eq(true)
    end
  end

  describe "Private method #unversioned_accept_header? =>" do
    it "Should return false if the header accept variable contains version 'application/vnd.#{Rails.application.secrets.my_app_accept_header}' in it." do
      @request.headers["Accept"] = "application/vnd.#{Rails.application.secrets.my_app_accept_header}"
      expect(@apiversion.send(:unversioned_accept_header?, @request)).to eq(false)
    end
    it "Should return true if no version is included with the header." do
      @request.headers["Accept"] = nil
      expect(@apiversion.send(:unversioned_accept_header?, @request)).to eq(true)
    end
  end

  describe "Private method #versioned_accept_header? =>" do
    it "Should return true if the header accept variable contains version 'application/vnd.#{Rails.application.secrets.my_app_accept_header}.v#{Rails.application.secrets.my_app_default_api_version}+json' in it." do
      @header = "application/vnd.#{Rails.application.secrets.my_app_accept_header}-v#{Rails.application.secrets.my_app_default_api_version}+json"
      @request.headers["Accept"] = @header
      expect(@apiversion.send(:versioned_accept_header?, @request)).to eq(@header)
    end
  end

  describe "Private method #version_default? =>" do
    it "Should return false when the proper header version is supplied." do
      @apiversion.stub(:unversioned_accept_header?).and_return(false)
      expect(@apiversion.send(:version_default?, @request)).to eq(false)
    end
    it "Should return true when no header is supplied, or a header different than 'application/vnd.#{Rails.application.secrets.my_app_accept_header}' is supplied." do
      @apiversion.stub(:unversioned_accept_header?).and_return(true)
      expect(@apiversion.send(:version_default?, @request)).to eq(true)
    end
  end

end

关于ruby-on-rails - rspec 在需要 stub 的私有(private)方法中测试私有(private)方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24200877/

相关文章:

ruby-on-rails - 事件模型序列化器 each_serializer 与序列化器

ruby-on-rails - Rspec 测试redirect_to :back

ruby-on-rails - pundit rspec - 未初始化的常量 UserPolicy,为什么?

c# - Rhino Mocks、void 和属性

ruby-on-rails - Dockerfile通过Rails自动运行乘客启动

Javascript URL 导航处理干扰其他 Javascript 部分

ruby-on-rails - 如何强制 nginx 在 HEAD 请求中包含 Content-Length header

ruby-on-rails-3 - 如何在 RubyMine 中只对一个规范文件运行一个测试

unit-testing - RhinoMocks 具有动态参数的期望

javascript - Jasmine 的 spyOn toHaveBeenCalled 方法的问题