13

I have a test like that:

lambda { post("/api/users", parameters) }.should change(User,:count).by(1)
lambda { post("/api/users", parameters) }.should_not change(ActionMailer::Base, :deliveries)

But I want to do it like that:

lambda { post("/api/users", parameters) }.should change(User,:count).by(1).and_not change(ActionMailer::Base, :deliveries)

Is it possible to do it without the need of two post calls?

Thanks

Owen S.
  • 7,665
  • 1
  • 28
  • 44

3 Answers3

11

I have found a solution to test it.

lambda{
  lambda { post("/api/users", params) }.should change(User,:count).by(1)
}.should change(ActionMailer::Base.deliveries, :count).by(1)
2

In my tests I am very strict: I want each test to test only a single thing. So I would always choose the first form, not the second.

Secondly I am not sure it is technically possible. The .should expects a block, which is executed before and after the lambda. Anyway, to my knowledge currently rspec does not support this (and imho with good reason).

nathanvda
  • 49,707
  • 13
  • 117
  • 139
0

I recently came across this issue when migrating some request tests over to feature test format for Capybara 2.1, and switching the testing syntax there from should-based to expect-based. To use the original question as the example, I had code like:

subject { -> { post("/api/users", parameters) } }
it { should change(User,:count).by(1) }
it { should_not change(ActionMailer::Base, :deliveries) }

Bringing this over to expect syntax in a scenario test presented some issues and yielded this kind of (working) clunkiness (sorry, not a big fan of explicitly nested lambdas/expects):

expect(-> { expect(post("/api/users", parameters)).to change(User,:count).by(1) }
).to_not change(ActionMailer::Base, :deliveries)

There are some great solutions to this issue in this StackOverflow thread which I tried and succeeded with, but what I ended up doing was simply follow the original format somewhat and split out each statement into its own scenario; something like:

feature "Add users via API" do
  given(:posting_parameters_to_api) { -> { post("/api/users", parameters) } }

  scenario "foo" do
    expect(posting_parameters_to_api).to change(User,:count).by(1)
  end

  scenario "bar" do
    expect(posting_parameters_to_api).to_not change(ActionMailer::Base, 
                                                    :deliveries)
  end
end

More verbose than the original request spec, but essentially working in the same way. Implementation will likely come down to personal taste.

Community
  • 1
  • 1
Paul Fioravanti
  • 16,423
  • 7
  • 71
  • 122