如何用Rails和RSpec正确测试类方法?HTTParty调用报错排查
问题:RSpec测试中HTTParty的post方法未被识别
环境:Rails 6.1、Ruby 2.6.3、RSpec 3.12
已安装的测试Gem依赖:
group :test do gem 'cucumber-rails', :require => false gem 'database_cleaner' gem 'rspec-rails' gem "capybara", ">= 2.15" gem "selenium-webdriver" gem "webdrivers" gem "httparty", "~> 0.18.1" end
测试文件spec/services/santander_payslip_controller.rb代码:
require 'rails_helper' require 'payslip' describe Payslip, type: :service do describe ".authenticate" do santander = Payslip::Santander.new "xxxx", "xxxx", "xxxx" context "given the client_id and client_secret" do it "fails without the digital certificate" do expect(santander.authenticate()).not_to eql('201') end end end end
被测试的Payslip::Santander类代码:
module Payslip class Santander include HTTParty def initialize(client_id, client_secret, account_id) @client_id = client_id @client_secret = client_secret @account_id = account_id @base_uri = Rails.configuration.santander_base_uri end def authenticate() url = @base_uri + '/token' params = { "client_id" => @client_id, "client_secret" => @client_secret, "grant_type" => "client_credentials" } payload = {body: params} response = post(url, payload).symbolize_key response.code end end
运行rspec命令后报错:
F Failures: 1) Payslip.authenticate given the client_id and client_secret fails without the digital certificate Failure/Error: response = post(url, payload).symbolize_key NoMethodError: undefined method `post' for #<Payslip::Santander:0x0000000108e51330> ./app/services/payslip.rb:23:in `authenticate' ./spec/services/santander_payslip_controller_spec.rb:11:in `block (4 levels) in <top (required)>' Finished in 0.01818 seconds (files took 3.95 seconds to load) 1 example, 1 failure Failed examples: rspec ./spec/services/santander_payslip_controller_spec.rb:10 # Payslip.authenticate given the client_id and client_secret fails without the digital certificate
错误原因
- HTTParty的
post是类方法,当你在类中include HTTParty时,实例无法直接调用该方法,必须通过类本身调用。 - 代码中存在两个语法错误:
symbolize_key应为复数形式symbolize_keys;类定义缺少闭合的end。
解决方案
1. 修复HTTParty调用方式
在authenticate方法中,将post改为self.class.post,通过类实例调用类级别的请求方法:
def authenticate() url = @base_uri + '/token' params = { "client_id" => @client_id, "client_secret" => @client_secret, "grant_type" => "client_credentials" } payload = {body: params} response = self.class.post(url, payload).symbolize_keys # 修正post调用和方法名 response.code end
2. 补全类的闭合end
在Payslip::Santander类和模块末尾添加缺失的end:
module Payslip class Santander include HTTParty def initialize(client_id, client_secret, account_id) @client_id = client_id @client_secret = client_secret @account_id = account_id @base_uri = Rails.configuration.santander_base_uri end def authenticate() url = @base_uri + '/token' params = { "client_id" => @client_id, "client_secret" => @client_secret, "grant_type" => "client_credentials" } payload = {body: params} response = self.class.post(url, payload).symbolize_keys response.code end end # 补全类的闭合end end # 补全模块的闭合end
3. 优化测试代码(可选)
调整测试结构,让实例化逻辑更规范,同时明确描述实例方法:
require 'rails_helper' require 'payslip' describe Payslip::Santander, type: :service do # 直接描述具体类更清晰 describe "#authenticate" do # 实例方法用#标识,类方法用. let(:santander) { Payslip::Santander.new("xxxx", "xxxx", "xxxx") } context "given the client_id and client_secret" do it "fails without the digital certificate" do expect(santander.authenticate).not_to eql('201') end end end end
4. 确认HTTParty加载正常
确保rails_helper.rb中没有排除HTTParty的加载,若有需要可在测试文件顶部显式添加require 'httparty'(通常require 'rails_helper'会自动加载所有Gem)。
内容的提问来源于stack exchange,提问作者Rafael Guedes
相关产品推荐
相关产品推荐

