Rails/RSpec: как протестировать метод #initialize?

Как указать поведение #initialize с помощью RSpec? Например здесь:

generator.rb

class Generator
  attr_accessor :seed

  def initialize(seed = nil)
    @seed = seed || pick_seed
  end

  def pick_seed
    Time.now.to_i
  end
end

generator_spec.rb

require 'generator'

describe Generator

  it "calls 'pick_seed' method unless seed specified" do
  end

end

Я хотел бы установить ожидание, что метод pick_seed вызывается из метода #initialize.


person avsej    schedule 25.12.2010    source источник


Ответы (1)


Для меня ожидания связаны с организацией разговоров между сотрудниками. Итак, вам нужно решить, является ли #pick_seed деталью внутренней реализации или частью интерфейса взаимодействующей роли?

Если pick_seed — это деталь реализации, то ожидание — неправильный инструмент для работы. И, поскольку у вас есть аксессор для семени, вы можете действовать таким образом (обратите внимание на одно утверждение для каждого примера):

class Generator
  attr_accessor :seed

  def initialize(seed = nil)
    @seed = seed || pick_seed
  end

  def pick_seed
    Time.now.to_i
  end
end

describe Generator do
  context "creating" do 
    context "when a seed is specified" do
      it "uses that seed" do
        seed = 123
        generator = Generator.new(seed)
        generator.seed.should == seed
      end
    end
    context "when a seed is not specified" do
      it "creates its own seed" do
        generator = Generator.new
        generator.seed.should_not be_nil
      end
    end
  end
end

OTOH, если сбор семени является частью роли "сборщика семян", то макеты полезны при разработке сборщика семян, а внедрение зависимостей является стандартным методом назначения ролей. Вы можете написать что-то вроде:

class GeneratorWithCollaborator
  attr_accessor :seed

  def initialize(seed = nil, seed_picker = self)
    @seed = seed || seed_picker.pick_seed
  end

  def pick_seed
    Time.now.to_i
  end
end

describe GeneratorWithCollaborator do
  context "creating" do
    context "when a seed is specified" do
      it "uses that seed" do
        seed = 123
        seed_picker = double('seed picker')
        seed_picker.should_not_receive(:pick_seed)
        generator = GeneratorWithCollaborator.new(seed, seed_picker)
        generator.pick_seed
      end
    end

    context "when a seed is not specified" do
      it "delegates to its seed picker" do
        seed_picker = double('seed picker')
        seed_picker.should_receive(:pick_seed)
        generator = GeneratorWithCollaborator.new(nil, seed_picker)
      end
    end
  end
end
person Sean DeNigris    schedule 25.12.2010
comment
В первом блоке кода не будет ли работать generator.seed.should_not be_nil, даже если семя такое же и не было сгенерировано? Но даже если вы проверите на generator.seed.should_not == seed, не будет ли этот тест зависеть от генератора случайных чисел, который не будет случайно создавать одно и то же семя время от времени? - person Marko Avlijaš; 10.10.2016
comment
Я бы, наверное, тоже сделал def pick_seed закрытым. Учитывая аксессуар, это не похоже на то, что должно быть общедоступно, но я думаю, что это невозможно узнать. - person cdmo; 08.07.2020