如果在另一个方法中调用方法,如何使用rspec进行测试?

时间:2017-06-16 19:18:51

标签: ruby-on-rails ruby rspec

我的方法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}}方法。

我该如何测试?

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