Как проверить класс Singleton? - PullRequest
11 голосов
/ 15 декабря 2009

Я использую RSpec и хочу проверить конструктор класса Singleton более одного раза.

Как я могу это сделать?

С уважением

Ответы [ 8 ]

17 голосов
/ 28 мая 2014

Синглтон-классы по сути делают это

def self.instance
  @instance ||= new
end

private_class_method :new

Таким образом, вы можете вообще обойтись без напоминания, вызвав приватный метод new с помощью send

let(:instance) { GlobalClass.send(:new) }

Хорошим преимуществом этого способа является то, что ни одно глобальное состояние не изменяется в результате выполнения ваших тестов.


Наверное, лучше, из этот ответ :

let(:instance) { Class.new(GlobalClass).instance }

Это создает анонимный класс, который наследует от GlobalClass, в котором хранятся все переменные экземпляра уровня класса. Затем он выбрасывается после каждого теста, оставляя GlobalClass нетронутым.

7 голосов
/ 24 сентября 2013
# singleton_spec.rb
require "singleton"

class Global
  include Singleton

  def initialize
    puts "Initializing"
  end
end

describe Global do
  before do
    Singleton.__init__(Global)
  end

  it "test1" do
    Global.instance
  end

  it "test2" do
    Global.instance
  end
end


% rspec singleton_spec.rb -fd
Global
Initializing
  test1
Initializing
  test2
3 голосов
/ 09 мая 2011

Один шаблон, который я видел, - это использование синглтона как подкласса реального класса. Вы используете версию Singleton в производственном коде, но базовый (не синглтонный) класс для тестирования.

Пример:

class MyClass
  attr_accessor :some_state

  def initialize
     @some_state = {}
  end
end

class MySingletonClass < MyClass
  include Singleton
end

... но я сам ищу лучший путь.

Часть моей проблемы заключается в том, что я использую JRuby и подключаюсь к Системным настройкам Java, которые являются глобальными. Остальное, я думаю, я могу сделать рефакторингом.

3 голосов
/ 15 декабря 2009

взгляните на http://blog.ardes.com/2006/12/11/testing-singletons-with-ruby:

require 'singleton'

class <<Singleton
  def included_with_reset(klass)
    included_without_reset(klass)
    class <<klass
      def reset_instance
        Singleton.send :__init__, self
        self
      end
    end
  end
  alias_method :included_without_reset, :included
  alias_method :included, :included_with_reset
end
2 голосов
/ 28 декабря 2009

Одна из причин, по которой люди используют синглтоны, потому что "глобальные переменные плохие, хорошо?" Синглтон - это глобальная переменная, секвестрируемая в пространстве имен и с ленивой реализацией. Подумайте, может ли истинная глобальная переменная упростить вещи, особенно если вам не нужна ленивая реализация.

1 голос
/ 15 декабря 2009

Преобразуйте его в класс, который может быть создан несколько раз. У этого есть побочный эффект (некоторые сказали бы выгоду) удаления природы Singleton из класса.

Посмотрите на это по-другому: вы обнаружили необходимость вызывать конструктор более одного раза. Почему должен класс создавать только один экземпляр? Какую выгоду предоставляет Singleton?

0 голосов
/ 15 декабря 2009

Вы можете просто сделать новый it и заблокировать для каждой спецификации. Разбейте свою спецификацию на тестируемое устройство. Используйте «до» и «после», чтобы настроить и очистить все, что вы сделали.

before(:each) и after(:each) выполняются для каждого it блока.

0 голосов
/ 15 декабря 2009

Позволяет ли RSpec выполнять действия перед тестированием? Таким образом, вы можете добавить еще один метод к вашему статическому классу, который очищает все, что сделано во время конструктора. Затем просто позвоните до каждого теста.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...