I am getting the following error when I run rake test with minitest:
$ rake test
DL is deprecated, please use Fiddle
Run options: --seed 55196
# Running:
.EE
Finished in 0.950979s, 3.1546 runs/s, 1.0515 assertions/s.
1) Error:
CategoryTest#test_invalid_without_name:
NoMethodError: undefined method `name=' for nil:NilClass
test/models/category_test.rb:14:in `test_invalid_without_name'
2) Error:
CategoryTest#test_invalid_without_long_name:
NoMethodError: undefined method `name=' for nil:NilClass
test/models/category_test.rb:19:in `test_invalid_without_long_name'
3 runs, 1 assertions, 0 failures, 2 errors, 0 skips
category_test.rb
require "test_helper"
class CategoryTest < ActiveSupport::TestCase
def category
#category = Category.new(name:'Homey')
end
def test_valid
assert category.valid?
end
def test_invalid_without_name
#category.name = nil
refute #category.valid?
end
def test_invalid_without_long_name
#category.name = "A"
refute #category.valid?
end
end
In my models I have the category.rb
class Category < ActiveRecord::Base
validates :name, presence: true
end
It seems that I have a nil class even though I am instantiating it in my category method. Any idea what is happening. I am just getting started using Minitest so not sure what is going on.
Do
def category
#category ||= Category.new(name:'Homey')
end
Then only use category not #category
Using a getter this way will set the instance var if it didnt exist before or retrieve the existing value
There are lots of ways to approach this, but the most straightforward would be to replace the category method with:
def setup
#category = Category.new(name:'Homey')
end
Related
I am trying to test that a specific mailer class is used when a model is saved. In my model I have:
class Foo < ActiveRecord::Base
def send_email
if some_condition
FooMailer.welcome.deliver_now
else
FooBarMailer.welcome.deliver_now
end
end
def
In my tests for Foo class I have the following
it 'uses the foo bar mailer' do
foo_mailer = class_spy(FooMailer)
subject.send_email
# some_condition will evaluate to false here, so we'll use the FooMailer
expect(foo_mailer).to have_received :welcome
end
When I run this test it fails with:
(ClassDouble(FooMailer) (anonymous)).welcome(*(any args))
expected: 1 time with any arguments
received: 0 times with any arguments
The issue would seem to be that you haven't swapped out the current definition of your mailer class with the spy, so your spy isn't receiving any messages. To replace it, you would use the stub_const method:
it 'uses the foo bar mailer' do
foobar_mailer = class_spy(FooBarMailer)
stub_const('FooBarMailer', foobar_mailer)
subject.send_email
# some_condition will evaluate to false here, so we'll use the FooBarMailer
expect(foobar_mailer).to have_received :welcome
end
This is a syntax sugar for the accepted answer.
foo_mailer = class_spy(FooMailer).as_stubbed_const
In model:
class State < ActiveRecord::Base
belongs_to :country
alias_method :abc, :xyz
def self.xyz
end
end
In log:
1.9.3-p551 :005 > State.abc
NameError: undefined method 'xyz' for class 'State'
I am new to alias_method in rails. Please help me out.
This is nothing to do with Rails, alias_method is part of ruby itself, which you really should learn before trying to use Rails.
Your problem here is that you've defined xyz as a class/singleton method, but alias_method called as you've done works on instance methods.
You can try the following :
class State
def self.xyz
ap 'inside'
end
self.singleton_class.send(:alias_method, :abc, :xyz)
end
Following should work :
>> State.xyz
>> State.abc
This is my first project in rails, and for some reason I fail to create my first unit test for my controller.
Basically, I have a main object Election, and each election may contain many voters.
The voters are created from a comma separated list of emails.
In this test, I want to test several lists of emails, to be sure that they are ingested correctly.
But for a reason I can't really grasp, my Voter model is not detected by my controller test.
So here is the related part of the code :
voters_controller_test.rb
require 'test_helper'
class VotersControllerTest < ActionController::TestCase
test "should add new voters" do
assert_difference('Voters.count', 2) do
post :create, voter: {election_id: 1, email_list: "me#me.fr, you#you.com"}
end
end
end
voter.rb
class Voter < ActiveRecord::Base
attr_accessor :email_list
belongs_to :election
validates :email, presence: true, :email => true
validates_uniqueness_of :email, :scope => [:election_id]
end
and the controller, voters_controller.rb
class VotersController < ApplicationController
def index
#election = Election.find(params[:election_id])
end
def create
#election = Election.find(params[:election_id])
emails = voter_params[:email_list].squish.split(',')
emails.each { |email| #voter = #election.voters.create(:email =>email) }
redirect_to election_voters_path(#election)
end
private
def voter_params
params.require(:voter).permit(:email_list)
end
end
I should probably mention that my application works fine, and that only the test is failing.
The exact error message is :
Run options: --seed 24993
# Running:
E.
Finished in 0.098560s, 20.2922 runs/s, 10.1461 assertions/s.
1) Error:
VotersControllerTest#test_should_add_new_voters:
NameError: uninitialized constant VotersControllerTest::Voters
/home/jll/Documents/01_perso/00_myelections/test/controllers/voters_controller_test.rb:6:in `block in <class:VotersControllerTest>'
This it is my very first ruby test, I heavily inspired myself from the rails testing tutorial.
Could you please provide me some insight on what I do wrong?
Thanks!
You're trying to assert the difference on the Voters model instead of the Voter model. This is what the code should look like.
assert_difference('Voter.count', 2) do
...
end
Remember, models will bear the singular version of the resource name while controllers will bear the plural name. E.g. The model is Voter while the controller is VotersController.
I'm trying to delete the embedded document from a parent document, and then add another embedded document but I am getting an error. Is my syntax not correct?
Error
NoMethodError: undefined method `create' for []:Array
Code
u = User.last
u.classes.destroy_all
u.classes.create(:name => "Philsophy") # I get the error right at this line
Ruby on Rails 3.0.3
Mongoid 2.0.0.beta.20
Thanks!
The relationship method classes returns an Array, not your base class.
To create and embed an object, you need to call the new method on the class,
then append it to classes.
Here is a working example that is probably close to what you intended. Hope that it helps you move on.
class User
include Mongoid::Document
field :name, type: String
embeds_many :classes, class_name: 'MyClass'
end
class MyClass
include Mongoid::Document
field :name, type: String
embedded_in :user
end
test/unit/user_test.rb
require 'test_helper'
class UserTest < ActiveSupport::TestCase
def setup
User.delete_all
end
test "embedded doc" do
User.create(name: 'Gary')
assert_equal(1, User.count)
u = User.last
u.classes.destroy_all
puts "u.classes.class: #{u.classes.class}"
u.classes << MyClass.new(:name => 'Philosophy')
user = User.find(u.id)
assert_equal('Philosophy', user.classes.first.name)
puts user.to_json
end
end
test output
Run options: --name=test_embedded_doc
# Running tests:
u.classes.class: Array
{"_id":"4fc62aeb7f11baa5b0000001","classes":[{"_id":"4fc62aeb7f11baa5b0000002","name":"Philosophy"}],"name":"Gary"}
.
Finished tests in 0.009929s, 100.7151 tests/s, 201.4302 assertions/s.
1 tests, 2 assertions, 0 failures, 0 errors, 0 skips
https://mongoid.github.io/old/en/mongoid/v3/relations.html#embeds_many
is helpful and points to many ways where you can add new objects to an existing object such as:
band.albums.build(name: "Violator")
band.albums.new(name: "Violator")
and if you have multiple objects
band.albums.concat(
Album.new(name: "Violator"),
Album.new(name: "101")
)
I have two problems but I'll post them as 2 different questions. Let's start with the first one.
class Order < AbstractOrder
def update_status
self.all_created.each do |order|
order.status = :in_progress
order.save
end
end
end
In my specs when I try to call
Order.update_status
I get an error saying :
Failure/Error: Order.update_status
NoMethodError:
undefined method `update_status' for #<Class:0x00000103f256a8>
# ./spec/models/order_spec.rb:17:in `block (3 levels) in <top (required)>'
Finished in 0.10439 seconds
3 examples, 1 failure
Why? I thought this was a class method not an instance method. If I create an order and do order.update_status it works. What is wrong and how do I fix it?
To bind the method to the class object you need to define it as self.update_status, and the self before all_created shouldn't be necessary:
class Order < AbstractOrder
def self.update_status
all_created.each do |order|
order.status = :in_progress
order.save
end
end
end