Reputation: 84
I have an ActiveRecord object which gets created/saved in approximately 50% of my RSpec suite. I want to stub a validation of it across the suite apart from the context where I am explicitly testing the behaviour of validation.
To achieve this, I stubbed it globally using config
config.before(:each) do
allow_any_instance_of(Activerecord::Abc).to receive(:abc_validate).and_return(true)
end
and then overwrote the stub in the specific context
context "Validations" do
context "abc_validate" do
before :each do
allow_any_instance_of(Activerecord::Abc).to receive(:abc_validate).and_call_original
end
it "should ..... " do
........
end
end
end
This meets my requirement. However, it is not efficient, as, although I need the stub only for approximately 50% of my RSpec test suite, I am actually stubbing it for every unit test. Even the unit tests which don't need the stub will have a stubbed function.
Is there a better way to do it?
I thought of one another approach: Instead of stubbing the method, I can re-open the class in RSpec and over-write the custom-validation function itself.
Activerecord::Abc.class_eval do
def abc_validate(testing_self = false)
testing_self ? super : true
end
end
However, this approach feels too hacky.
Version details -
Upvotes: 0
Views: 2665
Reputation: 1022
Personally I don't like the idea of using an invalid mock object across your entire suite. I think it's prone to bugs since tests will treat the object as a valid one and might use the functionality of the object which exposes it's invalidity, resulting in false negatives.
So I would suggest turning things around by using a valid object throughout your tests expect for the specific context in which you're testing it's creation and validations.
If creating a valid object requires a lot of set up you can use fixtures
or the FactoryGirl
gem to centrelize this logic in a single place. Creating a valid object will then be a simple issue of calling FactoryGirl.create(:abc)
.
Upvotes: 1