Clear Rspec match for change (Model ,: count) .by (1)

I work hard trying to keep my spec files as clean as possible. Using the "shoulda" gemstone and creating custom patterns that follow the same pattern.

My question is to create a custom match that will wrap expect{ post :create ... }.to change(Model, :count).by(1) and can be used in the same example groups with other "helpers". Details below:

Custom Mapping (Simplified)

 RSpec::Matchers.define :create_a_new do |model| match do |dummy| ::RSpec::Expectations::ExpectationTarget.new(subject).to change(model, :count).by(1) end end 

Working example

 describe 'POST create:' do describe '(valid params)' do subject { -> { post :create, model: agency_attributes } } it { should create_a_new(Agency) } end end 

This work works as long as I use subject lambda, and my coincidence is the only one in the group of examples.

Bad examples

Bad Example 1

Adding more examples to the same group will crash the other counter, since subject now a lambda instead of a controller instance.

 describe 'POST create:' do describe '(valid params)' do subject { -> { post :create, model: agency_attributes } } it { should create_a_new(Agency) } it { should redirect_to(Agency.last) } end end 

Bad Example 2

The 'shoulda' kernel expects me to define a before block, but this will become incompatible with my user match

 describe 'POST create:' do describe '(valid params)' do before { post :create, agency: agency_attributes } it { should create_a_new(Agency) } it { should redirect_to(Agency.last) } end end 

Expected Result

I am looking for a way to write my own match, which will correspond to the same group of examples as the other mappings, which means that my user connector must use the before block to execute the controller action, "unsuccessful example # 2" above, so I would like write your specifications. Is it possible?

Thanks for reading

+4
source share
1 answer

I do not think you can pass on your unsuccessful examples.

This is due to the fact that change really required by the lambda, since it must execute your account twice (once before and once after calling it). This is the reason I tend to not use it (or use it when isolating context).

What I usually do, instead of using a count server, checks three things:

  • The record is saved. If I assign the @model model, then I use expect(assigns(:model)).to be_persisted
  • The record is an instance of the expected model (although it may seem impractical, it is quite descriptive when using STIs). expect(assigns(:model)).to be_a(Model) .
  • Checking the last record in the database is the same as me, which just created `expect (assigns (: model)). eq (Model.last) ``

And so, as usual, I test the change server without using it. Of course, now you can create your own matches

 RSpec::Matchers.define :create_a_new do |model| match do |actual| actual.persisted? && actual.instance_of?(Participant) && (Participant.last == actual) end end 
+5
source

Source: https://habr.com/ru/post/1494861/


All Articles