Allow multiple StrongParametersMatchers to exist at once.

The provided RSpec example looks a bit contrived, but it corresponds to
this perfectly reasonable Minitest test case that was not working:

  class UserControllerTest < ActionController::TestCase
    should permit(:name).for(:create)
    should_not permit(:admin).for(:create)
  end

This instantiates two matchers at class load time, which resulted in the
second one overriding the double collection of the first one. Then when
the tests are executed, the first matcher would fail, because its double
is not listening to ActionController::Parameters#permit -- only the
second matcher's double collection gets activated.

This is fixed in Doublespeak by only creating one double collection per
class.
This commit is contained in:
Doug Orleans 2014-06-12 18:12:54 -04:00 committed by Elliot Winkler
parent ba744ba1b7
commit f81add5117
8 changed files with 32 additions and 39 deletions

View File

@ -1,5 +1,9 @@
# HEAD
### Bug fixes
* Fix `permit` so that it can be used more than once in the same test.
* Revert change to `validate_uniqueness_of` made in 2.6.0 so that it no longer
provides default values for non-primary, non-nullable columns. This approach
was causing test failures because it makes the assumption that none of these

View File

@ -213,7 +213,7 @@ module Shoulda
def set_double_collection
@double_collection =
Doublespeak.register_double_collection(::ActionController::Parameters)
Doublespeak.double_collection_for(::ActionController::Parameters)
@double_collection.register_stub(:require).to_return { |params| params }
@double_collection.register_proxy(:permit)

View File

@ -7,7 +7,7 @@ module Shoulda
class << self
extend Forwardable
def_delegators :world, :register_double_collection,
def_delegators :world, :double_collection_for,
:with_doubles_activated
def world

View File

@ -3,10 +3,8 @@ module Shoulda
module Doublespeak
# @private
class World
def register_double_collection(klass)
double_collection = DoubleCollection.new(klass)
double_collections_by_class[klass] = double_collection
double_collection
def double_collection_for(klass)
double_collections_by_class[klass] ||= DoubleCollection.new(klass)
end
def with_doubles_activated

View File

@ -251,7 +251,7 @@ module Shoulda
def register_subject_double_collection
double_collection =
Doublespeak.register_double_collection(subject.singleton_class)
Doublespeak.double_collection_for(subject.singleton_class)
double_collection.register_stub(target_method).
to_return(target_double)

View File

@ -25,6 +25,15 @@ describe Shoulda::Matchers::ActionController do
expect(@controller).to permit(:name, :age).for(:create)
end
it 'can be used more than once in the same test' do
controller_for_resource_with_strong_parameters(action: :create) do
params.require(:user).permit(:name)
end
expect(@controller).to permit(:name).for(:create)
expect(@controller).not_to permit(:admin).for(:create)
end
end
end

View File

@ -2,18 +2,19 @@ require 'spec_helper'
module Shoulda::Matchers::Doublespeak
describe World do
describe '#register_double_collection' do
it 'calls DoubleCollection.new with the given class' do
DoubleCollection.expects(:new).with(:klass)
describe '#double_collection_for' do
it 'calls DoubleCollection.new once with the given class' do
DoubleCollection.expects(:new).with(:klass).returns(:klass).once
world = described_class.new
world.register_double_collection(:klass)
world.double_collection_for(:klass)
world.double_collection_for(:klass)
end
it 'returns the newly created DoubleCollection' do
it 'returns the created DoubleCollection' do
double_collection = Object.new
DoubleCollection.stubs(:new).with(:klass).returns(double_collection)
world = described_class.new
expect(world.register_double_collection(:klass)).to be double_collection
expect(world.double_collection_for(:klass)).to be double_collection
end
end
@ -40,9 +41,9 @@ module Shoulda::Matchers::Doublespeak
DoubleCollection.stubs(:new).
with(:klass3).
returns(double_collections[2])
world.register_double_collection(:klass1)
world.register_double_collection(:klass2)
world.register_double_collection(:klass3)
world.double_collection_for(:klass1)
world.double_collection_for(:klass2)
world.double_collection_for(:klass3)
world.with_doubles_activated { block_called = true }
@ -57,32 +58,13 @@ module Shoulda::Matchers::Doublespeak
world = described_class.new
DoubleCollection.stubs(:new).returns(double_collection)
world.register_double_collection(:klass)
world.double_collection_for(:klass)
begin
world.with_doubles_activated { raise 'error' }
rescue RuntimeError
end
end
it 'does not allow multiple DoubleCollections to be registered that represent the same class' do
double_collections = [stub, stub]
sequence = sequence('with_doubles_activated')
double_collections[0].expects(:activate).never
double_collections[0].expects(:deactivate).never
double_collections[1].expects(:activate).in_sequence(sequence)
double_collections[1].expects(:deactivate).in_sequence(sequence)
world = described_class.new
DoubleCollection.stubs(:new).
returns(double_collections[0]).then.
returns(double_collections[1])
world.register_double_collection(:klass1)
world.register_double_collection(:klass1)
world.with_doubles_activated { }
end
end
end
end

View File

@ -2,10 +2,10 @@ require 'spec_helper'
module Shoulda::Matchers
describe Doublespeak do
describe '.register_double_collection' do
describe '.double_collection_for' do
it 'delegates to its world' do
Doublespeak.world.expects(:register_double_collection).with(:klass)
described_class.register_double_collection(:klass)
Doublespeak.world.expects(:double_collection_for).with(:klass)
described_class.double_collection_for(:klass)
end
end