I have a test for a controller that receives uploaded files, and I’ve gotten past a lot of obstacles, but I’ve got one that I just can’t understand. Using RSpec 2.12, Ruby 2.0.0, Rails 3.2.21.
Code from spec/controllers/auto_controller.rb:
…
describe AutoController do
GoodEmails.each_with_index do | params, ix |
before(:each) do
Upload.delete_all
Log.delete_all
post :create, params
end
it "Valid posts for good email #{ix}" do
response.code.should eq "201"
Upload.count.should eq 1
Log.count.should eq 1
Log.last.message.should match(/Kobo Sales Upload/)
end
end
…
Some of the code from app/controllers/auto_controller.rb:
def create
begin
for i in (1 .. params[:attachments].to_i)
attachment = params["attachment#{i}"]
if attachment.present? && attachment.original_filename.is_a?(String) && attachment.original_filename.split(".").last == 'zip'
upload = Upload.create!(filename: attachment.original_filename, content: attachment.read, uploaded_at: Time.now, file_descr: params[:subject] )
Log.log_message("Sales Upload #{
upload.id} received (#{params[:subject]})", distributor_id: distributor_id, task: 'auto’, data: {params: clean(params)})
end
end
render status: :created, nothing: true
rescue StandardError
render status: :created, nothing: true
Log.log_message("Bad email received; subject: #{params[:subject]}", data: {params: clean(params)})
end
end
I’m getting the test rejected message:
Failure/Error: Upload.count.should eq 1
expected: 1
got: 0
(compared using ==)
When I set a breakpoint at the end of the controller code, I see that response.code = 201, Upload.count = 1, Log.count = 1, and Log.last.message = "Kobo Sales Upload”
However, when I set a breakpoint in the spec file right inside the “it” block, I see response.code = 201, Upload.count = 0, and Log.count = 0.
My expectation was that the “before(:each)” would run before each test, so that I would see a break in the spec, then four breaks in the controller, then a break in the spec and four more breaks in the controller. Ideally, I would like to run the before code once, then perform the four tests on the result, and then iterate for the second GoodEmail. I think that I could accomplish that by using “before(:all)”, but apparently you cannot put a “post” command inside a before(:all) block, so I can’t do that.
So, I have two questions:
1) Why aren’t the database records still there when I get to the “it” block?
2) Is there a “more correct way ” (in terms of RSpec best practices) to structure this test sequence?