ruby on rails 4 - Use rspec to test class methods are calling scopes -
i have created rspec tests scopes (scope1
, scope2
, scope3
) , pass expected add tests class method have called controller (the controller calls scopes indirectly via class method):
def self.my_class_method(arg1, arg2) scoped = self.all if arg1.present? scoped = scoped.scope1(arg1) end if arg2.present? scoped = scoped.scope2(arg2) elsif arg1.present? scoped = scoped.scope3(arg1) end scoped end
it seems bit redundant run same scope tests each scenario in class method when know pass assume need ensure different scopes called/applied dependant on args being passed class method.
can advise on rspec test like.
i thought might along lines of
expect_any_instance_of(mymodel.my_class_method(arg1, nil)).to receive(:scope1).with(arg1, nil)
but doesn't work.
i appreciate confirmation that's necessary test in situation when i've tested scopes anyway reassurring.
the rspec code wrote testing internal implementation of method. should test method returns want return given arguments, not in way. way, tests less brittle. example if change scope1
called, won't have rewrite my_class_method
tests.
i creating number of instances of class , call method various arguments , check results expect.
i don't know scope1
, scope2
do, made example arguments name
attribute model , scope methods retrieve models except name. obviously, whatever real arguments , scope
methods should put in tests, , should modify expected results accordingly.
i used to_ary
method expected results since self.all
call returns activerecord association , therefore wouldn't otherwise match expected array. use includes
, does_not_includes
instead of eq
, perhaps care order or something.
describe mymodel describe ".my_class_method" # helpful use factorygirl here # note bang (!) version of let let!(:my_model_1) { mymodel.create(name: "alex") } let!(:my_model_2) { mymodel.create(name: "bob") } let!(:my_model_3) { mymodel.create(name: "chris") } context "with nil arguments" let(:arg1) { nil } let(:arg2) { nil } "returns all" expected = [my_model_1, my_model_2, my_model_3] expect_my_class_method_to_return expected end end context "with first argument equal model's name" let(:arg1) { my_model_1.name } let(:arg2) { nil } "returns except models name matching argument" expected = [my_model_2, my_model_3] expect_my_class_method_to_return expected end context "with second argument equal model's name" let(:arg1) { my_model_1.name } let(:arg2) { my_model_2.name } "returns except models name matching either argument" expected = [my_model_3] expect_my_class_method_to_return expected end end end end private def expect_my_class_method_to_return(expected) actual = described_class.my_class_method(arg1, arg2).to_ary expect(actual).to eq expected end end
Comments
Post a Comment