diff options
| author | Robert | 2017-10-20 18:18:13 +0200 |
|---|---|---|
| committer | Robert | 2017-10-20 18:18:13 +0200 |
| commit | dce18aaeaf16a3109b801ba4cd8fd02d0cf564c0 (patch) | |
| tree | ee256e930cd014ab507e2c18d170db318e398c5a | |
| parent | 2315feae844a39ae9e86939b090bed0d2997f482 (diff) | |
| download | chouette-core-dce18aaeaf16a3109b801ba4cd8fd02d0cf564c0.tar.bz2 | |
A promising approach to complete db stubbing
| -rw-r--r-- | spec/models/faster_specs_spec.rb | 50 | ||||
| -rw-r--r-- | spec/support/faster/model_stubber.rb | 15 | ||||
| -rw-r--r-- | spec/support/faster/model_stubber/implementation.rb | 106 | ||||
| -rw-r--r-- | spec/support/faster/model_stubber/object_cache.rb | 23 |
4 files changed, 194 insertions, 0 deletions
diff --git a/spec/models/faster_specs_spec.rb b/spec/models/faster_specs_spec.rb new file mode 100644 index 000000000..2c97d1055 --- /dev/null +++ b/spec/models/faster_specs_spec.rb @@ -0,0 +1,50 @@ +RSpec.describe 'Faster Specs', type: :faster do + + shared_examples_for 'correct behavior' do + + it 'finds workbench' do + expect( referential.workbench ).to eq(workbench) + end + + it 'finds referentials' do + expect( workbench.referentials ).to eq([referential]) + end + + end + + context 'in DB' do + let( :workbench ){ create :workbench } + let( :referential ){ create(:referential, workbench: workbench) } + + it_behaves_like 'correct behavior' + end + + context 'stubbed' do + let( :workbench ){ stub_model Workbench } + let( :referential ){ stub_model( Referential, workbench: workbench ) } + + it_behaves_like 'correct behavior' + + context 'workbench belongs to organisation' do + it 'workbench has no orgnaisation' do + expect( workbench.organisation ).to be_nil + end + it 'but it can be set' do + organisation = stub_model Organisation + workbench.organisation = organisation + expect( workbench.organisation ).to eq(organisation) + end + it 'and by setting it we get the reverse relation working' do + organisation = stub_model Organisation + workbench.organisation = organisation + expect( organisation.workbenches ).to be_eql([workbench]) + end + it 'can also be constructed that way' do + organisation = stub_model Organisation + workbench = stub_model Workbench, organisation: organisation + expect( workbench.organisation ).to eq(organisation) + expect( organisation.workbenches ).to be_eql([workbench]) + end + end + end +end diff --git a/spec/support/faster/model_stubber.rb b/spec/support/faster/model_stubber.rb new file mode 100644 index 000000000..789f5c2d2 --- /dev/null +++ b/spec/support/faster/model_stubber.rb @@ -0,0 +1,15 @@ +require_relative 'model_stubber/implementation' + +module ModelStubber + def stub_model klass, **params + klass.new.tap do | model | + Implementation.new(model, params).setup + end + end +end + + +RSpec.configure do | conf | + # Empty Helper's cache before each example or create a helper? + conf.include ModelStubber, type: :faster +end diff --git a/spec/support/faster/model_stubber/implementation.rb b/spec/support/faster/model_stubber/implementation.rb new file mode 100644 index 000000000..9ee1f417a --- /dev/null +++ b/spec/support/faster/model_stubber/implementation.rb @@ -0,0 +1,106 @@ +require_relative './object_cache' + +module ModelStubber + + # Get out of RSpec's example's namespace + class Implementation + + attr_reader :model, :params + + def initialize model, **params + @model = model + @params = params + end + + def setup + ObjectCache.add_to_cache model + stub_all_relations + params.each(&method(:setup_att)) + self + end + + + private + + # Workers + def setup_att key, value + setup_reflection( model, key, value) && return + end + + def setup_belongs_to reflection, model, key, value + model.stub(key){value} + has_manys = + value.class.reflect_on_all_associations(:has_many).select{|v| v.foreign_type == "#{model.class.name.underscore.pluralize}_type" } + has_manys.each do | has_many | + value.send( has_many.name ) << model + end + true + end + + def setup_reflection model, key, value + case reflection = model.class.reflections[key.to_s] + when ActiveRecord::Reflection::BelongsToReflection + setup_belongs_to reflection, model, key, value + # when ActiveRecord::Reflection::HasManyReflection + # setup_has_many reflection, model, key, value + else + false + end + end + + + def stub_all_relations + reflections.each(&method(:stub_relation)) + end + + def stub_belongs_to name + singleton.send :attr_reader, name + define_singleton_method "#{name}=" do |value| + instance_variable_set("@#{name}", value) + has_manys = + value.class.reflect_on_all_associations(:has_many).select{|v| v.foreign_type == "#{self.class.name.underscore.pluralize}_type" } + has_manys.each do | has_many | + value.send( has_many.name ) << self + end + value + end + end + + def stub_has_many name + empty = [] + mystub(model, name){empty} + end + + def stub_relation name, reflection + case reflection + when ActiveRecord::Reflection::BelongsToReflection + stub_belongs_to name + when ActiveRecord::Reflection::HasManyReflection + stub_has_many name + end + + end + + # Meta + def define_singleton_method name, &blk + singleton.module_eval do + define_method(name, &blk) + end + end + def mystub rcv, name, &blk + class << rcv; self end + .module_eval do + define_method(name, &blk) + end + end + + # Lazy Values + def reflections + @__reflections__ ||= model.class.reflections + end + + def singleton + @__singleton__ ||= class << model; self end + end + end +end diff --git a/spec/support/faster/model_stubber/object_cache.rb b/spec/support/faster/model_stubber/object_cache.rb new file mode 100644 index 000000000..5749be76f --- /dev/null +++ b/spec/support/faster/model_stubber/object_cache.rb @@ -0,0 +1,23 @@ +module ModelStubber + module ObjectCache extend self + + def add_to_cache model + model.id = cache[model.class].keys.last.try(:succ) || 1 + cache[model.class].update( model.id => model ) + end + + def empty_cache! + @__cache__ = _cache + end + + private + + def cache + @__cache__ ||= _cache + end + def _cache + Hash.new { |h, k| h[k] = {} } + end + + end +end |
