Ruby 测试失败-一个类方法调用另一个类方法(“预期:1次带参数,收到0次”)

Ruby 测试失败-一个类方法调用另一个类方法(“预期:1次带参数,收到0次”),ruby,rspec,stub,stubbing,stubs,Ruby,Rspec,Stub,Stubbing,Stubs,我的问题: 我试图存根一个类方法,该方法返回该类的一个实例,但在题为“使用CSV数据创建实例”的测试中,我得到了以下错误: 上下文: require "csv" class QuestionData attr_reader :questions def initialize(questions) @questions = questions end def self.load_questions(file = './app/lib/question_list.cs

我的问题:

我试图存根一个类方法,该方法返回该类的一个实例,但在题为“使用CSV数据创建实例”的测试中,我得到了以下错误:

上下文:

require "csv"

class QuestionData

  attr_reader :questions

  def initialize(questions)
    @questions = questions
  end

  def self.load_questions(file = './app/lib/question_list.csv', questions = [])
    self.parse_csv(file, questions)
    self.new(questions)
  end

  def self.parse_csv(file, questions)
    CSV.foreach(file) do |row|
      time_limit, text, correct_answer, option_2, option_3 = row[0],
       row[1], row[2], row[3], row[4]
      questions << { time_limit: time_limit, text: text,
        correct_answer: correct_answer, option_2: option_2, option_3: option_3
      }
    end
  end

end
require './app/models/question_data'

describe QuestionData do

  subject(:question_data_instance) { described_class.new(data) }
  let(:question_data_class) { described_class }
  let(:CSV) { double(:CSV, foreach: nil) }
  let(:questions) { [] }
  let(:file) { double(:file) }
  let(:data) do
    [{
      time_limit: 10,
      text: "Who was the legendary Benedictine monk who invented champagne?",
      correct_answer: "Dom Perignon",
      option_2: "Ansgar",
      option_3: "Willibrord"
      },
      {
        time_limit: 12,
        text: "Name the largest freshwater lake in the world?",
        correct_answer: "Lake Superior",
        option_2: "Lake Victoria",
        option_3: "Lake Huron"
      }]
  end

  describe '#questions' do
    it "has an array of question data from CSV" do
      expect(question_data_instance.questions).to eq(data)
    end
  end

  describe '.parse_csv' do
    it "parses CSV data into hash data" do
      expect(CSV).to receive(:foreach).with(file)
      question_data_class.parse_csv(file, questions)
    end
  end

  describe '.load_questions' do
    it "calls '.parse_csv' method" do
      expect(question_data_class).to receive(:parse_csv).with(file, questions)
      question_data_class.load_questions(file, questions)
    end

    it "creates an instance with CSV data" do
      allow(question_data_class).to receive(:load_questions).with(file, questions).and_return(question_data_instance)
      allow(question_data_class).to receive(:new).with(data).and_return(question_data_instance)
      expect(question_data_class).to receive(:new).with(data).and_return(question_data_instance)
      question_data_class.load_questions(file, questions)
    end
  end

  describe '.new' do
    it "creates a new instance with CSV data" do
      expect(question_data_class).to receive(:new).with(data).and_return(question_data_instance)
      question_data_class.new(data)
    end
  end

end
代码(如下所示)工作-
QuestionData.load\u questions
从CSV文件加载数据,并调用
QuestionData.new
,将数据作为参数。然而,我对
.load\u questions
方法的测试给出了上述错误。调用时,
QuestionData
类的double没有接收带有
数据的
.new
的存根

我曾尝试研究如何测试返回另一个存根或实例的存根,但似乎找不到相关的答案

我真的非常感谢任何帮助或建议,提前非常感谢

代码:

require "csv"

class QuestionData

  attr_reader :questions

  def initialize(questions)
    @questions = questions
  end

  def self.load_questions(file = './app/lib/question_list.csv', questions = [])
    self.parse_csv(file, questions)
    self.new(questions)
  end

  def self.parse_csv(file, questions)
    CSV.foreach(file) do |row|
      time_limit, text, correct_answer, option_2, option_3 = row[0],
       row[1], row[2], row[3], row[4]
      questions << { time_limit: time_limit, text: text,
        correct_answer: correct_answer, option_2: option_2, option_3: option_3
      }
    end
  end

end
require './app/models/question_data'

describe QuestionData do

  subject(:question_data_instance) { described_class.new(data) }
  let(:question_data_class) { described_class }
  let(:CSV) { double(:CSV, foreach: nil) }
  let(:questions) { [] }
  let(:file) { double(:file) }
  let(:data) do
    [{
      time_limit: 10,
      text: "Who was the legendary Benedictine monk who invented champagne?",
      correct_answer: "Dom Perignon",
      option_2: "Ansgar",
      option_3: "Willibrord"
      },
      {
        time_limit: 12,
        text: "Name the largest freshwater lake in the world?",
        correct_answer: "Lake Superior",
        option_2: "Lake Victoria",
        option_3: "Lake Huron"
      }]
  end

  describe '#questions' do
    it "has an array of question data from CSV" do
      expect(question_data_instance.questions).to eq(data)
    end
  end

  describe '.parse_csv' do
    it "parses CSV data into hash data" do
      expect(CSV).to receive(:foreach).with(file)
      question_data_class.parse_csv(file, questions)
    end
  end

  describe '.load_questions' do
    it "calls '.parse_csv' method" do
      expect(question_data_class).to receive(:parse_csv).with(file, questions)
      question_data_class.load_questions(file, questions)
    end

    it "creates an instance with CSV data" do
      allow(question_data_class).to receive(:load_questions).with(file, questions).and_return(question_data_instance)
      allow(question_data_class).to receive(:new).with(data).and_return(question_data_instance)
      expect(question_data_class).to receive(:new).with(data).and_return(question_data_instance)
      question_data_class.load_questions(file, questions)
    end
  end

  describe '.new' do
    it "creates a new instance with CSV data" do
      expect(question_data_class).to receive(:new).with(data).and_return(question_data_instance)
      question_data_class.new(data)
    end
  end

end

问题是,您正在取消呼叫:

允许(问题\数据\类)。接收(:加载\问题)。使用(文件)
如果仍希望执行调用,则需要添加:

和_调用_original
因此,将执行原始方法,并且代码将在原始块上调用新方法

但问题是,您不需要存根类,您只需要更改存根,因为您正在对double调用该方法,它将尝试在类中执行该方法,因此您可能需要将第二个测试更改为:

description'.load_questions'do
它“创建一个包含CSV数据的实例”这样做
预期(已描述的类)。接收(:新)。带有(数据)。和返回(问题数据实例)
已描述\u类。加载\u问题(文件)
结束
结束

问题是您正在对以下电话进行中断:

允许(问题\数据\类)。接收(:加载\问题)。使用(文件)
如果仍希望执行调用,则需要添加:

和_调用_original
因此,将执行原始方法,并且代码将在原始块上调用新方法

但问题是,您不需要存根类,您只需要更改存根,因为您正在对double调用该方法,它将尝试在类中执行该方法,因此您可能需要将第二个测试更改为:

description'.load_questions'do
它“创建一个包含CSV数据的实例”这样做
预期(已描述的类)。接收(:新)。带有(数据)。和返回(问题数据实例)
已描述\u类。加载\u问题(文件)
结束
结束

你好,aledustet,非常感谢你回答我的问题,我很抱歉,我才意识到我最初发布的代码在提问之前没有发挥应有的作用。我现在对它做了非常轻微的修改,现在它100%工作了(但我仍然不知道如何测试它,并在测试中得到相同的错误)。再次深表歉意,非常感谢您抽出时间。我已经尝试将你的
描述的课程
想法融入到我的新测试中,但到目前为止还没有成功(再次感谢你的提示!)。嗨,aledustet,非常感谢你回答我的问题,我很抱歉,我才意识到我最初发布的代码在提问之前不起作用。我现在对它做了非常轻微的修改,现在它100%工作了(但我仍然不知道如何测试它,并在测试中得到相同的错误)。再次深表歉意,非常感谢您抽出时间。我已经试着将你的
描述的课程
思想融入到我的新测试中,但到目前为止还没有成功(再次感谢你的提示!)。