Rails Rspec 允许在一行中调用多个方法
Rails Rspec allow multiple method call in one line
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
以上是裁剪作业 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: "a$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)>'
当 运行 此测试时,您正在创建 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
除非您想使用 any_instance_of
(这是一种代码味道),否则您需要对 Users::Delete
方法进行存根处理,使其 returns 成为双精度值并将期望值放在双精度值上:
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
let(:double) do
instance_double('Users::Delete')
end
before do
allow(Users::Delete).to receive(:new).and_return(double)
end
it 'calls right service method' do
expect(double).to receive(:destroy_all)
run_users_rake_task
end
end
end
然而,这实际上只是告诉我们服务对象的 API 很笨重,您应该编写一个 class 方法来实例化和执行:
module Users
class Delete
# ...
def self.destroy_all(users)
new(users).destroy_all
end
end
end
desc 'Remove credential state users who no longer request for confirm otp within 10 minutes'
#...
Users::Delete.destroy_all(@user)
# ...
end
require 'rails_helper'
describe 'users rake tasks' do
# ...
context 'when remove credential state users who no longer request for confirm otp within 10 minutes' do
# ...
it 'calls right service method' do
expect(Users::Delete).to receive(:destroy_all)
run_users_rake_task
end
end
end
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
以上是裁剪作业 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: "a$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)>'
当 运行 此测试时,您正在创建 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
除非您想使用 any_instance_of
(这是一种代码味道),否则您需要对 Users::Delete
方法进行存根处理,使其 returns 成为双精度值并将期望值放在双精度值上:
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
let(:double) do
instance_double('Users::Delete')
end
before do
allow(Users::Delete).to receive(:new).and_return(double)
end
it 'calls right service method' do
expect(double).to receive(:destroy_all)
run_users_rake_task
end
end
end
然而,这实际上只是告诉我们服务对象的 API 很笨重,您应该编写一个 class 方法来实例化和执行:
module Users
class Delete
# ...
def self.destroy_all(users)
new(users).destroy_all
end
end
end
desc 'Remove credential state users who no longer request for confirm otp within 10 minutes'
#...
Users::Delete.destroy_all(@user)
# ...
end
require 'rails_helper'
describe 'users rake tasks' do
# ...
context 'when remove credential state users who no longer request for confirm otp within 10 minutes' do
# ...
it 'calls right service method' do
expect(Users::Delete).to receive(:destroy_all)
run_users_rake_task
end
end
end