Why am I getting that/how can I get around it?
Code is:
class UserController < ApplicationController
def index
#users=User.all
end
end
Spec is:
require 'spec_helper'
describe UserController do
describe "GET index" do
it "assigns #users" do
user = User.create(:email => 'bob#test.com', :password=>'12', :password_confirmation=> '12')
get :index
assigns(:users).should eq([user])
end
it "renders the index template" do
get :index
response.should render_template("index")
end
end
end
Failures:
1) UserController GET index assigns #users
Failure/Error: get :index
ActionController::RoutingError:
No route matches {:controller=>"user"}
# ./spec/controllers/user_controller_spec.rb:8:in `block (3 levels) in <top (required)>'
2) UserController GET index renders the index template
Failure/Error: get :index
ActionController::RoutingError:
No route matches {:controller=>"user"}
# ./spec/controllers/user_controller_spec.rb:13:in `block (3 levels) in <top (required)>'
Finished in 0.13146 seconds
2 examples, 2 failures
Routes are:
TimeTracker::Application.routes.draw do
devise_for :users
resources :users
root :to => 'users#index'
end
Your controller class name is in singular (UserController), it should be UsersController
Related
I have the following table TodoList :
class CreateTodoLists < ActiveRecord::Migration
def change
create_table :todo_lists do |t|
t.string :list_name
t.date :list_due_date
t.timestamps null: false
end
end
end
I create crud methods:
def create_todolist(params)
todolist = TodoList.create(params)
end
And i have the followging tests:
context "the code has to create_todolist method" do
it { is_expected.to respond_to(:create_todolist) }
it "should create_todolist with provided parameters" do
expect(TodoList.find_by list_name: "mylist").to be_nil
due_date=Date.today
assignment.create_todolist(:name=> 'mylist', :due_date=>due_date)
testList = TodoList.find_by list_name: 'mylist'
expect(testList.id).not_to be_nil
expect(testList.list_name).to eq "mylist"
expect(testList.list_due_date).to eq due_date
expect(testList.created_at).not_to be_nil
expect(testList.updated_at).not_to be_nil
end
end
When i launch the test give me the following errors:
assignment code has create_todolist method should create_todolist with provided parameters
Failure/Error: assignment.create_todolist(:name=> 'mylist', :due_date=>due_date)
ActiveRecord::UnknownAttributeError:
unknown attribute 'name' for TodoList.
# ./assignment/assignment.rb:25:in `create_todolist'
# ./spec/assignment_spec.rb:171:in `block (4 levels) in <top (required)>'
# ./spec/assignment_spec.rb:14:in `block (2 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# NoMethodError:
# undefined method `name=' for #<TodoList:0x007f96dd0d13f0>
# ./assignment/assignment.rb:25:in `create_todolist'
Finished in 0.14136 seconds (files took 1.66 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./spec/assignment_spec.rb:168 # Assignment rq03 rq03.2 assignment code has create_todolist method should create_todolist with provided parameters
I think it's because params attributes does not match exactly the same TodoList attributes. How to modify my create_todolist to change keys values ?
Your field is called list_name, but you're passing :name => 'myList'.
The same for due_date and list_due_date.
Should be
assignment.create_todolist(list_name:'mylist', list_due_date: due_date)
I hope this is not a specific error and it may be a logic error that can help others as well.
I want to test my controller index method, and i have a before method with an active record query. The problem is that i can't figure what is wrong with my test because i get this error only when using rspec and not when i test it manually.
Controller
class BlogsController < ApplicationController
before_filter :archive_months
def archive_months
#months = Blog.find(:all, :select=>:publish_date, :order=>"publish_date DESC")
.select{ |p| p.publish_date <= Date.today }
.group_by{ |p| [p.year, p.month, p.publish_date.strftime("%B")] }
end
Test
require 'rails_helper'
RSpec.describe BlogsController, :type => :controller do
before(:each) do
#post1 = create(:blog)
end
describe "GET #index" do
it "shows all blog posts" do
get :index
expect(response).to have_http_status(200)
end
end
end
Test output
1) BlogsController GET #index shows all blog posts
Failure/Error: get :index
NoMethodError:
undefined method `<=' for nil:NilClass
# ./app/controllers/blogs_controller.rb:178:in `block in archive_months'
# ./app/controllers/blogs_controller.rb:177:in `select'
# ./app/controllers/blogs_controller.rb:177:in `archive_months'
If i run the #months query on the page or in rails console it works well, but on my test in does not work.
It seems you have one or more Blog objects in your test database that don't have a publish_date attribute set. That's why .select{ |p| p.publish_date <= Date.today } raises the error.
All,
I am getting the following undefined method errors below when running my rspec tests. When I have gotten this error before I had a method misspelled or my order of execution caused it. I checked both along with some other posts on StackOverflow, but nothing helped. Can anyone offer any guidance?
Rspec Failures:
FFFF
Failures:
1) Post vote methods #up_votes counts the number of votes with value = 1
Failure/Error: expect(#post.up_votes ).to eq(3)
NoMethodError:
undefined method `up_votes' for #<Post:0x007fe92f381a38>
# ./spec/models/post_spec.rb:14:in `block (4 levels) in <top (required)>'
2) Post vote methods #down_votes counts the number of votes with values = -1
Failure/Error: expect(#post.down_votes ).to eq(2)
NoMethodError:
undefined method `down_votes' for #<Post:0x007fe92a18c228>
# ./spec/models/post_spec.rb:20:in `block (4 levels) in <top (required)>'
3) Post vote methods #points returns the sum of all down and up votes
Failure/Error: expect(#post.points ).to eq(1) # 3 - 2
NoMethodError:
undefined method `points' for #<Post:0x007fe92986c620>
# ./spec/models/post_spec.rb:26:in `block (4 levels) in <top (required)>'
4) Vote validations value validation only allows -1 or 1 as values
Failure/Error: expect(#post.up_votes).to eq((-1) || eq(1))
NoMethodError:
undefined method `up_votes' for nil:NilClass
# ./spec/models/vote_spec.rb:5:in `block (4 levels) in <top (required)>'
Post_rspec
require 'rails_helper'
describe Post do
describe "vote methods" do
before do
#post = Post.create(title: 'Post title', body: 'Post bodies must be pretty long.')
3.times { #post.votes.create(value: 1) }
2.times { #post.votes.create(value: -1) }
end
describe '#up_votes' do
it "counts the number of votes with value = 1" do
expect(#post.up_votes ).to eq(3)
end
end
describe '#down_votes' do
it "counts the number of votes with values = -1" do
expect(#post.down_votes ).to eq(2)
end
end
describe '#points' do
it "returns the sum of all down and up votes" do
expect(#post.points ).to eq(1) # 3 - 2
end
end
end
end
vote_spec file
describe Vote do
describe "validations" do
describe "value validation" do
it "only allows -1 or 1 as values" do
expect(#post.up_votes).to eq((-1) || eq(1))
end
end
end
end
Post.rb
class Post < ActiveRecord::Base
has_many :comments, dependent: :destroy
has_many :votes
has_one :summary
belongs_to :user #means the post table has the user table's primary key in it
belongs_to :topic
mount_uploader :avatar, AvatarUploader
default_scope {order('created_at DESC')}
validates :title, length: {minimum: 5}, presence: true
validates :body, length: {minimum: 20}, presence: true
def markdown_title
(render_as_markdown).render(self.title).html_safe
end
def markdown_body
(render_as_markdown).render(self.body).html_safe
end
private
def render_as_markdown
renderer = Redcarpet::Render::HTML.new
extensions = {fenced_code_blocks: true}
redcarpet = Redcarpet::Markdown.new(renderer, extensions)
#return redcarpet
end
end
For the post_spec.rb errors, check the Post model (see file app/models/post.rb) has the following methods defined in it:
up_votes
down_votes
points
Consider including the code for post.rb in your original question too.
For the vote_spec.rb errors, there is no #post variable, it will be nil. This error message hints at this:
Failure/Error: expect(#post.up_votes).to eq((-1) || eq(1))
NoMethodError: undefined method `up_votes' for nil:NilClass
I have a simple restaurant class that looks like this:
module Restaurant
class Identity
attr_reader :name, :location
def initialize (name, location)
#name = name
#location = location
end
end
end
My factory looks like this:
FactoryGirl.define do
factory :restaurant, :class => Restaurant::Identity do |f|
f.name "Alfredos"
f.location "Andheri"
end
end
And my test is written like this:
describe Restaurant::Identity do
subject { build(:restaurant) }
its(:name) {should_not be_nil}
its(:location) {should_not be_nil}
end
But when I run this, I get
1) Restaurant::Identity name
Failure/Error: subject { build(:restaurant) }
ArgumentError:
wrong number of arguments (0 for 2)
# ./lib/restaurant.rb:7:in `initialize'
# ./spec/restaurant_spec.rb:9:in `block (2 levels) in <top (required)>'
# ./spec/restaurant_spec.rb:11:in `block (2 levels) in <top (required)>'
Why is this happening? What am I doing wrong?
Ok so the solution is to use initialize_with in your factory girl setup:
FactoryGirl.define do
factory :restaurant, :class => Restaurant::Identity do |f|
f.name "Alfredos"
f.location "Andheri"
initialize_with { new(name, location) } # add this line
end
end
ref: https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#custom-construction
I have a Directory controller and a Files controller. I'm testing the Files controller. I've created valid attributes for the File and I'm trying to mock_model the Directory to get the test to pass. The GET tests all work, but none of the POST tests work. The POST tests all give the error: "Directory expected, got String."
describe FilesController do
def valid_attributes {
:name => "test",
:reference_id => 1,
:location => "/path/to/directory",
:software => "excel",
:software_version => "2010",
:directory => mock_model(Directory)
}
end
describe "POST create" do
describe "with valid params" do
it "creates a new AssemblyFile" do
expect {
post :create, :assembly_file => valid_attributes
}.to change(AssemblyFile, :count).by(1)
end
it "assigns a newly created assembly_file as #assembly_file" do
post :create, :assembly_file => valid_attributes
assigns(:assembly_file).should be_a(AssemblyFile)
assigns(:assembly_file).should be_persisted
end
it "redirects to the created assembly_file" do
post :create, :assembly_file => valid_attributes
response.should redirect_to(AssemblyFile.last)
end
end
end
1) FilesController POST create with valid params creates a new File
Failure/Error: post :create, :file => valid_attributes
ActiveRecord::AssociationTypeMismatch:
Directory(#87017560) expected, got String(#49965220)
# ./app/controllers/files_controller.rb:60:in `new'
# ./app/controllers/files_controller.rb:60:in `create'
# ./spec/controllers/files_controller_spec.rb:79:in `block (5 levels) in <top (required)>'
# ./spec/controllers/files_controller_spec.rb:78:in `block (4 levels) in <top (required)>'
If I look at the test.log file, it shows that assembly is a string ("assembly" => "1011"). So I'm not sure why the mock_model isn't creating an object?
I've tried using stub! instead of mock_model, but that gets complicated because the create! used for stub! needs a lot of its own valid variables set and I don't really want to have to set a whole bunch of other valid attributes for that when I'm not trying to even test the Directory controller at all.
What am I doing wrong in my approach here?
Pass the id of the mock in the params hash instead of the mock itself. You'll also need to stub the find method so the mock is available in the controller action:
#directory = mock_model(Directory)
Directory.stub(:find).with(#directory.id).and_return(#directory)
post :create, :assembly_file => valid_attributes.merge(:directory_id => #directory.id)
# in controller
#directory = Directory.find(params[:assembly_file][:directory_id]) # => returns the mock