'Why are tests failing in Ruby on Rails?
I am studying the book "Agile Web Development with Rails 4". In it, at one moment associated with testing, it gives two errors
Error:
ProductsControllerTest#test_should_update_product:
ArgumentError: unknown keywords: :id, :product
test/controllers/products_controller_test.rb:42:in `block in <class:ProductsControllerTest>'
Error:
ProductsControllerTest#test_should_create_product:
ArgumentError: unknown keyword: :product
test/controllers/products_controller_test.rb:26:in `block (2 levels) in <class:ProductsControllerTest>'
test/controllers/products_controller_test.rb:25:in `block in <class:ProductsControllerTest>'
In the same place, the author indicates how to fix them: in the 'setup do' add
@update = {
title: 'Lorem Ipsum',
description: 'Wibbles are fun!',
image_url: 'lorem.jpg',
price: 19.95
}
In 'should_create_product' replace
post products_url, params: { product: { description: @product.description, image_url: @product.image_url, price: @product.price, title: @product.title } }
with
post :create, product: @update
And in 'should_update_product' replace
patch product_url(@product), params: { product: { description: @product.description, image_url: @product.image_url, price: @product.price, title: @product.title } }
with
patch :update, id: @product, product: @update
However, after these fixes, the tests continue to give the same errors. How to fix it?
EDITED: I tried to replace with
post :create, params: { product: @update }
and
patch :update, params: { id: @product, product: @update }
Now it gives to me another errors:
Error:
ProductsControllerTest#test_should_create_product:
URI::InvalidURIError: bad URI(is not URI?): "http://www.example.com:80create"
test/controllers/products_controller_test.rb:26:in `block (2 levels) in <class:ProductsControllerTest>'
test/controllers/products_controller_test.rb:25:in `block in <class:ProductsControllerTest>'
Error:
ProductsControllerTest#test_should_update_product:
URI::InvalidURIError: bad URI(is not URI?): "http://www.example.com:80update"
test/controllers/products_controller_test.rb:42:in `block in <class:ProductsControllerTest>'
Solution 1:[1]
You're mixing up two different kinds of tests.
The first is functional controller tests in the form of ActionController::TestCase
which you probably have in your book. These are tests that create a mocked request object and pass it to an instance of the controller. The use of these is greatly discouraged outside of legacy apps since they tend to let tons of bugs through. In functional tests you would write post :create, params: { product: { ... }}
because you are actually calling the create method on the controller instance.
The second is integration tests in the form of ActionDispatch::IntegrationTest
where you send actual HTTP requests to your Rails application. This is the modern approach and it's just as fast as functional tests in modern versions of Rails which was not the case when the book was written.
In an integration test you pass a path or url:
post '/products', params: { product: ... }
A second issue is the mandatory separation the of keyword parameters that was introduced in Rails 5.
In previous versions of Rails you could call:
get '/foo', bar: 1, baz: 2
And Rails would treat any unknown keys (not params, headers, format, etc) as parameters which was the source of many bugs. In Rails 5+ you explicitly need to pass parameters in the params option.
get '/foo', params: { bar: 1, baz: 2 }
I would suggest you complement the book with some more modern sources or get a newer edition as quite a lot has changed since Rails 4 and following a book that old in Rails 6 is going to be painful.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |