首页 > 解决方案 > Rails Rspec 允许在一行中调用多个方法

问题描述

desc 'Remove credential state users who no longer request for confirm otp within 10 minutes'
 task failed_user_cleaner: :environment do
 puts "Daily UserRecord Cleaning CronJob started - #{Time.now}"

 @user = User.with_state("credentials").with_last_otp_at(Time.now - 10.minutes)
 Users::Delete.new(@user).destroy_all

 puts "Daily UserRecord Cleaning CronJob ended - #{Time.now}"
end

以上是crop job rake 文件代码。

然后我尝试了很多次,发现了很多次。但是我找不到为上述工作编写单元测试用例的方法。

帮助我正确编写测试用例。

这是我的规格代码

require 'rails_helper'

describe 'users rake tasks' do
  before do
    Rake.application.rake_require 'tasks/users'
    Rake::Task.define_task(:environment)
  end

  context 'when remove credential state users who no longer request for confirm otp within 10 minutes' do
    let(:user) { create(:user, last_otp_at: Time.now - 11.minutes, state: "credentials") }
    let (:run_users_rake_task) do
      Rake.application.invoke_task 'users:failed_user_cleaner'
    end

    it 'calls right service method' do
      @users = Users::Delete.new([user])
      expect(@users).to receive(:destroy_all)

      run_users_rake_task
    end
  end
end

这是错误日志

失败:

  1) users rake tasks when remove credential state users who no longer request for confirm otp within 10 minutes calls right service method
 Failure/Error: expect(@users).to receive(:destroy_all)
 
   (#<Users::Delete:0x0000556dfcca3a40 @user=[#<User id: 181, uuid: nil, phone: "+66969597538", otp_secret: nil, last_otp_at: "2021-09-30 09:32:24.961548000 +0700", created_at: "2021-09-30 09:43:24.973818000 +0700", updated_at: "2021-09-30 09:43:24.973818000 +0700", email: nil, avatar: "https://dummyimage.com/300x300/f04720/153572.png?t...", refresh_token: "eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2MzI5Njk4MDQsImV4c...", first_name_en: "Jenise", first_name_th: "Damion", last_name_en: "McCullough", last_name_th: "Beatty", nationality: "TH", thai_national_id: nil, thai_laser_code: nil, company_id: 200, role: nil, state: "credentials", date_of_birth: "2020-10-30 00:00:00.000000000 +0700", deleted_at: nil, password_digest: "$2a$04$jfR9X9ci06602tlAyLOoRewTK1lZ12vJ2cZ9Dc2ov4F...", username: "zreejme238", shopname: nil, access_token: nil, locked_at: nil, login_attempts: 0, locale: "th", scorm_completed: false>]>).destroy_all(*(any args))
       expected: 1 time with any arguments
       received: 0 times with any arguments
 # ./spec/tasks/users_spec.rb:19:in `block (3 levels) in <top (required)>'

标签: ruby-on-railsrubyunit-testingrspec

解决方案


Users::Delete在运行此测试时创建了两个实例,一个在测试中,一个在任务中。由于未使用测试中的实例,因此期望它接收消息是不正确的。

Rspec有一个期望expect_any_instance_of可以解决这个问题,但是考虑阅读整个页面,因为它可能会创建脆弱或不稳定的测试。如果您想使用此方法,您的测试将类似于:

it 'calls right service method' do
  expect_any_instance_of(Users::Delete).to receive(:destroy_all)

  run_users_rake_task
end

就我个人而言,我会检查预期的用户是否被删除,例如:

it 'removes the user' do
  expect { run_users_rake_task }.to change { User.exists?(id: @user.id) }.to(false)
end

推荐阅读