Я использую RSpec и хочу проверить конструктор класса Singleton более одного раза.Как проверить класс Singleton?
Как это сделать?
С наилучшими пожеланиями
Я использую RSpec и хочу проверить конструктор класса Singleton более одного раза.Как проверить класс Singleton?
Как это сделать?
С наилучшими пожеланиями
посмотреть на http://blog.ardes.com/2006/12/11/testing-singletons-with-ruby: "? Глобальные переменные плохо, m'kay"
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
Допускают ли RSpec вы выполнить предтестовое действие? Итак, вы можете добавить к вам еще один метод статического класса, который очистил бы все, что было сделано во время конструктора. Затем просто вызовите это до каждого теста.
RSpec имеет блоки «до» и «после». http://rspec.info/documentation/before_and_after.html –
Но конструктор не будет вызываться дважды из-за шаблона Singleton. – brainfck
Рефакторинг в класс, который можно построить несколько раз. У этого есть побочный эффект (кто-то сказал бы выгоду) об удалении природы Singleton из класса.
Посмотрите на это по-другому: вы обнаружили необходимость вызова конструктора более одного раза. Почему должен класс только построить один экземпляр? Какая польза от предоставления Singleton?
Конструктор не требует вызова более одного раза, но я хочу, чтобы мои спецификации были ясными - поэтому я тестирую только одну часть конструктора в каждой спецификации. – brainfck
Вы можете просто создать новый it
и блокировать для каждой спецификации. Разделите свою спецификацию на тестируемый блок. Используйте «до» и «после», чтобы настроить и очистить все, что вы сделали.
before(:each)
и after(:each)
выполнены для каждого блока it
.
Одна из причин, люди используют одиночка, потому что Синглтон - это глобальная переменная, секвестрированная в пространстве имен и с ленивым экземпляром. Подумайте, может ли истинная глобальная переменная упростить вещи, особенно если вам не нужна ленивая инстанция.
Один узор, который я видел, имеет одноэлементный подкласс класса. Вы используете версию Singleton в производственном коде, но базовый (не одиночный) класс для тестирования.
Пример:
class MyClass
attr_accessor :some_state
def initialize
@some_state = {}
end
end
class MySingletonClass < MyClass
include Singleton
end
... но я ищу лучший способ себя.
Часть моей проблемы заключается в том, что я использую JRuby и подключаюсь к настройкам Java-системы, которые являются глобальными. Остальное, я думаю, я могу реорганизовать.
# 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
Ключ «Singleton .__ init __ (Global)». Это прибило его для меня. Спасибо. – iHiD
Проблема в том, что это сбрасывает синглтон. Если какие-либо другие части вашего приложения опираются на глобальное состояние, которое было установлено ранее, это сломается. Например, если вы используете шаблон реестра, то как вы можете протестировать реестр, не нарушая тесты для компонентов, использующих реестр? –
классы Singleton в основном это сделать
def self.instance
@instance ||= new
end
private_class_method :new
Таким образом, вы можете обойти запоминанием вообще, вызвав частный метод новый, используя отправить
let(:instance) { GlobalClass.send(:new) }
Хорошая выгода этого способа является то, что нет глобальное состояние изменяется в результате выполнения ваших тестов.
Вероятно, лучший путь, от this answer:
let(:instance) { Class.new(GlobalClass).instance }
Это создает анонимный класс, который наследует от GlobalClass
, что все переменные экземпляра класса уровня хранятся в этом затем выбрасываются после каждого. тест, оставив GlobalClass
нетронутым.
Это простое, прямое решение. –
Спасибо, это было очень полезно. – chrisco
Проблема с этим - глобальное состояние изменяется при выполнении ваших тестов. См. Мой ответ ниже для более чистого способа. –