MiniTest parent and child from factory in test - ruby-on-rails

I'm getting the following error when running my test.
NoMethodError: undefined method 'departure_date' for nil:NilClass
Here is the test.
test "successful disbursement should respond with success" do
post :disbursement, {id: #invoice.invoice_id, trip: attributes_for(:trip)}
assert_response :success
end
In the setup portion of the test I'm creating the following.
setup do
#controller = Api::V1::InvoicesController.new
#invoice = create(:invoice)
#trip = create(:trip)
end
The trip factory looks like this.
FactoryGirl.define do
factory :trip do
depart_airport "MCI"
arrive_airport "ORD"
passenger_first_name "Joe"
passenger_last_name "Business"
passenger_count 1
departure_date {10.days.from_now}
invoice
end
end
The invoice factory looks like this.
FactoryGirl.define do
factory :invoice do
sequence(:invoice_id) { |n| "INV#{n}"}
merchant
amount 500.00
item_count 5
paid false
currency "GBP"
invoice_type "pre-flight"
end
end
Can't quite figure out how to make sure the invoice has a trip. I'm guessing this is why the test can't find the departure_date it should.

From what I understand, you are trying to associate the trip and invoice. If my understanding is correct, try this.
setup do
#controller = Api::V1::InvoicesController.new
#invoice = create(:invoice)
#trip = create(:trip, invoice: #invoice)
end

Related

testing nested attributes in rails

before I ask the question I want to give a little background on the models. I have a user_conversation model(through table) which accepts attributes from conversations and messages models. The create action and before action are given below.
before_action :logged_in_user
before_action :validate_conversation, only: :create
def create
redirect_to home_path unless current_user
#conversation = UserConversation.new conversation_params
#conversation.user = current_user
#conversation.conversation.messages.first.user = current_user
#conversation.save!
activate_unread
redirect_to user_conversation_path(current_user,#conversation)
end
Private
def validate_conversation
#user = User.find params[:user_id]
if params[:user_conversation][:conversation_attributes]["subject"].blank?
redirect_to new_user_conversation_path(#user)
flash[:danger] = "Subject cannot be blank"
else params[:user_conversation][:conversation_attributes][:messages_attributes]["0"]["body"].blank?
redirect_to new_user_conversation_path(#user)
flash[:danger] = "Message cannot be blank"
end
end
def conversation_params
params.require(:user_conversation).permit(:recipient_id, conversation_attributes: [:subject, messages_attributes: [:body]])
end
I was trying to write an integration tests for the post request of user_conversation. The test is given below.
require 'test_helper'
class ConversationCreateTest < ActionDispatch::IntegrationTest
def setup
#user = users(:user_a)
#conversation = conversations(:convo_one)
end
test "invalid creation of a user conversation no subject" do
log_in_as(#user)
get new_user_conversation_path(#user)
post user_conversations_path(#user), user_conversation: {:recipient_id => #user.id, :conversation_attributes => {:subject => "this is a subject",
:message_attributes => {"0" => {:body => "sending a message"}}}}
end
I get the following error message when I run the command.
1) Error:
ConversationCreateTest#test_invalid_creation_of_a_user_conversation_no_subject:
NoMethodError: undefined method `[]' for nil:NilClass
app/controllers/user_conversations_controller.rb:63:in `validate_conversation'
test/integration/conversation_create_test.rb:13:in `block in <class:ConversationCreateTest>'
191 runs, 398 assertions, 0 failures, 1 errors, 0 skips
I have been trying to debug the problem for about 2 hours. I have checked the test log files and it says internal server error 500. I have tried commenting certain lines of codes to narrow down the problem but not really sure what the problem is. Any help would be appreciated.
In rails, validations are made with the ActiveModel::Validators.
So you can simply validate your model like this:
User:
class User
has_many :conversations, through: "user_conversations"
end
Conversation:
class Conversation
has_many :users, through: "user_conversations"
validates_presence_of :subject, :messages
end
See more here about validations
So if you then need to validate your model you can call:
conversation = Conversation.create(subject: nil)
conversation.errors.full_messages # => ["Subject can't be blank"]
I think you'll need to rewrite a bunch of things in your app, and if you took the code above you can simply test this thing within a model (unit) test.
Which, by the way, is no longer needed because you don't want to test the rails provided validators. You probably just want to test your own validators.

FactoryGirl has many trait creation not working

I'm trying to get FactoryGirl to create quiz_question. But it's only creating the belongs to factory(quiz_campaign) in the test DB environment, not the has many factory(quiz_question).
quiz_campaign.rb
FactoryGirl.define do
trait :with_quiz_questions do
after_create do |campaign|
FactoryGirl.create(:quiz_question, quiz_campaign: campaign)
end
end
end
factory :quiz_campaign do
subdomain "macy"
end
quiz_question.rb
FactoryGirl.define do
factory :quiz_question do
message "What's your question"
end
end
quiz_home_page.feature
Given(/^there's a subdomain for a quiz campaign$/) do
#quiz_campaign = create(:quiz_campaign)
end
When(/^I visit the quiz campaign microsite subdomain url$/) do
visit_with_subdomain microsite_home_path, subdomain: #quiz_campaign.subdomain
end
Resolved it by not using traits. It seems like using traits causes more complex solution than needed

Rails Factory Girl RSpec Testing Has-Many Relationship of Nested Resources

Note: A business has many catalogs and has products, and a catalog has many products. The associations are properly defined and they are working in the application front end. But I can't make this test pass. I am using friendly_id so you will see me using #model.slug on some of the find methods
I am trying this test out:
describe "GET 'show'" do
before do
#business = FactoryGirl.create(:business)
#catalog = FactoryGirl.create(:catalog, :business=>#business)
#product1 = FactoryGirl.create(:product, :business=>#business, :catalog=>#catalog)
#product2 = FactoryGirl.create(:product, :business=>#business, :catalog=>#catalog)
end
def do_show
get :show, :business_id=>#business.slug, :id=>#catalog.slug
end
it "should show products" do
#catalog.should_receive(:products).and_return([#product1, #product2])
do_show
end
end
with this factory (note that a business and catalog factory is define somewhere else, and they are associations):
FactoryGirl.define do
sequence :name do |n|
"product#{n}"
end
sequence :description do |n|
"This is description #{n}"
end
factory :product do
name
description
business
catalog
end
end
with this show action:
def show
#business = Business.find(params[:business_id])
#catalog = #business.catalogs.find(params[:id])
#products = #catalog.products.all
respond_with(#business, #catalog)
end
but I am getting this error:
CatalogsController GET 'show' should show products
Failure/Error: #catalog.should_receive(:products).and_return([#product1, #product2])
(#<Catalog:0x000001016185d0>).products(any args)
expected: 1 time
received: 0 times
# ./spec/controllers/catalogs_controller_spec.rb:36:in `block (3 levels) in <top (required)>'
furthermore, this code block will also indicate that Business model has not received the find method:
Business.should_receive(:find).with(#business.slug).and_return(#business)
The problem here is that the #catalog instance variable you set up in the spec is not the same as the #catalog instance variable in the controller.
#catalog in the spec will never receive any messages sent to #catalog in the controller.
What you need to do instead is to change this in your spec:
#catalog.should_receive(:products).and_return([#product1, #product2])
to
Catalog.any_instance.should_receive(:products).and_return([#product1, #product2])
Check out the RSpec documentation on any_instance.should_receive here: https://www.relishapp.com/rspec/rspec-mocks/v/2-6/docs/message-expectations/expect-a-message-on-any-instance-of-a-class

Ruby On Rails Function Testing :index with a polymorphic model

I have a polymorphic model called Address, I am trying to currently write some basic function tests for this model and controller. For the controller I am at a loss on how to go about this. For example I have another model called Patient, each Patient will have an address, so i have started writing the following function test, but i have no idea how to use "get" with a nested polymorphic resource. Now I was able to find some polymorphic test information on Fixtures here: http://api.rubyonrails.org/classes/Fixtures.html
but this will not help me test against the index. Any help is much appreciated im at a total and complete loss here.
FILE: test/functional/addresses_controller_test.rb
require 'test_helper'
class AddressesControllerTest < ActionController::TestCase
setup do
#address = addresses(:of_patient)
#patient = patients(:one)
activate_authlogic
end
test "patient addresses index without user" do
get :index <<<<<<<<<<<< what goes here????
assert_redirected_to :login
end
end
Assuming your controller is setup the way I think it might be:
def index
if #current_user
#addresses = #current_user.addresses.all
else
redirect_to login_path
end
end
Then the test will probably look like this:
test "patient addresses index without user" do
get :index, :patient_id => #patient.id
assert_redirected_to :login
end
test "patient addresses with user" do
#current_user = #patient
get :index, :patient_id => #patient.id
assert_response :success
end
The thing to keep in mind is that the index method needs the patient_id to process.

How to test a before_save method including accossioations with rspec

I'm having a problem testing the following model:
class Bill < ActiveRecord::Base
belongs_to :consignee
before_save :calc_rate
def calc_rate
self.chargeableweight = self.consignee.destination.rate * self.weight
end
end
The consignee model:
class Consignee < ActiveRecord::Base
belongs_to :destination
has_many :bills
end
The controllers are not touched yet.
The behavior of the app is correct (follow up question: are there any performance problems with that solution?) - but the the test break.
You have a nil object when you didn't
expect it! You might have expected an
instance of Array. The error occurred
while evaluating nil.*
Thank you in advice,
Danny
update:
This bill test breaks using factory girl:
describe Bill do
it "should call the calc_rate method" do
bill = Factory.build(:bill)
bill.save!
bill.should_receive(:calc_rate)
end
end
You have a nil object when you didn't expect it!
Factories:
Factory.define :destination do |f|
f.airport_code "JFK"
end
Factory.define :consignee do |f|
...
f.association :destination
end
Factory.define :bill do |f|
f.association :consignee
f.weight 10
f.chargeableweight 20.0
f.after_create do |bill|
bill.calc_rate
end
describe Consignee do
it "should calculate the rate" do
#pending
#make sure this spec is passing first, so you know your calc_rate method is fine.
end
it "should accept calc_rate before save" do
cosignee = mock("Consignee")
consignee.should_receive(:calc_rate).and_return(2) # => stubbing your value
end
end
I didn't spool up a rails app to test this code, but this should get you close. also, assuming that the columns chargeable_rate, weight, etc are columns on the model, you dont need to call self. Ruby will implicitly expect self if there is no instance method or variable of that name available it will automatically look for class methods.

Resources