我正在研究一个必须通过rpsec测试的问题。问题是该方法使用与内置ruby方法.count
鉴于我无法更改rspec测试,是否可以覆盖.count
以表现不同?如果没有,是否有更好的方法来解决这个问题?
这是我试图传递的rspec测试
subject = FinancialSummary.one_day(user: user, currency: :usd)
expect(subject.count(:deposit)).to eq(2)
我的代码:
class FinancialSummary
def self.one_day(user: user, currency: currency)
one_day_range = Date.today.beginning_of_day..Date.today.end_of_day
find_transaction(user.id, currency).where(created_at: one_day_range)
end
def self.find_transaction(user_id, currency)
Transaction.where(user_id: user_id,
amount_currency: currency.to_s.upcase
)
end
end
输出:
[#<Transaction:0x00007f9b39c2e9b8
id: 1,
user_id: 1,
amount_cents: 1,
amount_currency: "USD",
category: "deposit",
created_at: Sat, 10 Mar 2018 18:46:53 UTC +00:00,
updated_at: Sat, 10 Mar 2018 18:46:53 UTC +00:00>,
#<Transaction:0x00007f9b3d0dbc38
id: 2,
user_id: 1,
amount_cents: 2000,
amount_currency: "USD",
category: "deposit",
created_at: Sat, 10 Mar 2018 18:47:43 UTC +00:00,
updated_at: Sat, 10 Mar 2018 18:47:43 UTC +00:00>,
#<Transaction:0x00007f9b3d0b3fa8
id: 7,
user_id: 1,
amount_cents: 1200,
amount_currency: "USD",
category: "withdraw",
created_at: Mon, 05 Mar 2018 02:22:42 UTC +00:00,
updated_at: Tue, 06 Mar 2018 18:48:20 UTC +00:00>]
它打印出来,我认为是正确的信息,直到测试尝试通过count
category: 'deposit'
进行交易。然后我收到此错误消息:
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: deposit: SELECT COUNT(deposit) FROM "transactions" WHERE "transactions"."user_id" = ? AND "transactions"."amount_currency" = ?
编辑更多信息
答案 0 :(得分:1)
在撰写此答案时可能会做出一些假设,并且可能会根据更新的规范进行修改
覆盖count
是一个坏主意,因为查看或使用您的代码的其他人不会知道这不是他们所了解和理解的计数。
而是考虑为此创建一个范围,如
class FinancialSummary < ApplicationRecord
scope :one_day, ->(user:,currency:) { where(user: user, currency: currency) } #clearly already a scope
scope :transaction_type, ->(transaction_type:) { where(category: transaction_type) }
end
然后测试成为
subject = FinancialSummary.one_day(user: user, currency: :usd)
expect(subject.transaction_type(:deposit).count).to eq(2)
SQL现在变为:
SELECT COUNT(*)
FROM
"transactions"
WHERE
"transactions"."user_id" = ?
AND "transactions"."amount_currency" = "usd"
AND "transactions"."category" = "deposit"
仍然非常易懂且易于阅读,无需破坏我们明确使用的计数方法。
答案 1 :(得分:0)
目前还不清楚计数消息被发送到哪个对象,因为我不知道FinancialSummary.one_day(user: user, currency: :usd)
返回什么,但似乎你说count
是一个方法,无论它返回什么,你无法改变。 FinancialSummary.one_day(user: user, currency: :usd).class
返回什么?
也许一种解决方案是通过添加alias_method :count, :account_count
然后在您的测试调用expect(subject.account_count(:deposit)).to eq(2)
如果你可以在你的问题中发布FinancialSummary#one_day方法会更容易。