开发者

Assert multiple change expectations within a single lambda request

开发者 https://www.devze.com 2023-04-08 20:28 出处:网络
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)

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


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)


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).


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号