Подтвердить что ты не робот

Как проверить класс Singleton?

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

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

С наилучшими пожеланиями

4b9b3361

Ответ 1

посмотрите 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

Одиночные классы по существу делают это

def self.instance
  @instance ||= new
end

private_class_method :new

Итак, вы можете обойти memoization вообще, вызывая частный метод new, используя send

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

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


Вероятно, лучший способ, от этого ответа:

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

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

Ответ 3

# 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

Ответ 4

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

Пример:

class MyClass
  attr_accessor :some_state

  def initialize
     @some_state = {}
  end
end

class MySingletonClass < MyClass
  include Singleton
end

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

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

Ответ 5

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

Ответ 6

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

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

Ответ 7

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

Ответ 8

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

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