我的方法create
:
module AnswerCreator
class Creator
def initialize(answer)
@answer = answer
end
def create
test_cases_results = run_test_cases
@answer.attempt = get_attempt_number
@answer.correct = correct?(test_cases_results)
ActiveRecord::Base.transaction do
@answer.save!
save_test_cases_results(test_cases_results)
Scorer::Changer.new(@answer).change
end
ComputeAnswerSimilarityJob.perform_later(@answer)
end
...
end
end
我对它进行了以下测试:
it "creates the answer with the right attempt number, create the test case results and add the answer to be processed in background" do
answer_test_case_result_count = AnswerTestCaseResult.count
jobs_count = enqueued_jobs.size
user = create(:user)
team = create(:team)
question = create(:question)
create_pair(:test_case, question: question)
create(:answer, question: question, user: user, team: team)
answer = build(:answer, question: question, user: user, team: team)
# These answers must be ignored >>
create(:answer, question: question, user: user)
create(:answer, question: question, team: team)
create(:answer, user: user, team: team)
described_class.new(answer).create
expect(answer.new_record?).to be_falsey
expect(answer.attempt).to eq 2
expect(AnswerTestCaseResult.count).to eq answer_test_case_result_count + 2
expect(enqueued_jobs.size).to eq jobs_count + 1
end
此Creator
类在创建Answer对象时处理创建逻辑。我的Changer
类处理与Answer对象关联的得分逻辑。我不想在Creator
内测试此逻辑,但我想确保调用来自change
的{{1}}方法。
我该如何测试?
答案 0 :(得分:2)
所以你要测试这行代码:
Scorer::Changer.new(@answer).change
我最初的想法是推荐allow_any_instance_of,但正如您在该链接中看到的那样,RSpec团队会建议不要这样做。但是,如果您愿意,可以在调用Creator#create
之前将其放入测试用例中:
expect_any_instance_of(Scorer::Changer).to receive(:change).and_call_original
Withoug expect_any_instance_of
,据我所知,你必须存根构造函数:
fake_answer = "???" # change to the value of 'answer' in your test case
fake_changer = Scorer::Changer.new fake_answer
expect(Scorer::Changer).to receive(:new).and_return fake_changer
expect(fake_changer).to receive(:change).and_call_original
这种事情有点乏味,但是当功能在私有状态方面有很多进展时会发生什么。例如,如果您将Scorer::Changer.new
电话移至Creator#initialize
?
attr_reader :changer
def initialize(answer)
@answer = answer
@changer = Scorer::Changer.new @answer
end
然后你需要做一些不那么简短的事情:
fake_answer = "???"
creator = AnswerCreator::Creator.new fake_answer
expect(creator.changer).to receive(:change).and_call_original
creator.create