I am pretty new to rspec. How do I write functional test for following piece of code.
class FooController < ApplicationController
def new
#title = "Log in to Mint"
#msg = session[:msg]
session[:msg] = nil
end
end
How about something like this:
describe FooController do
describe "GET new" do
it "assigns 'Log in to Mint' to #title" do
get :new
assigns(:title).should == "Log in to Mint"
end
it "assigns message session to #msg" do
session[:msg] = "a message"
get :new
assigns(:msg).should == "a message"
end
it "sets message session to nil" do
get :new
session[:msg].should be_nil
end
end
end
See also: Rspec: testing assignment of instance variable
Related
I'm setting up specs to test whether or not a job calls a method under certain conditions.
This is what I have so far:
describe RandomJob do
context "when payload[:type] = MyModel" do
let!(:my_model) { create :my_model }
let!(:payload) { { type: "MyModel", id: my_model.id } }
context "when Model exists" do
it "calls MyModel.fire! with payload" do
RandomJob.perform_now(payload)
expect_any_instance_of(MyModel).to receive(:fire!).with(payload)
end
end
context "when Model does not exist" do
it "does not call MyModel.fire!" do
RandomJob.perform_now(payload)
expect_any_instance_of(MyModel).not_to receive(:fire!)
end
end
end
end
Just to be sure my way of testing worked. I setup my job like this:
class RandomJob < ApplicationJob
def perform(payload)
#payload = payload
fire_model!
end
private
def fire_model!
my_model&.fire! #payload
end
def my_model
MyModel.find(#payload[:id])
end
end
I expected the first test to pass, and the second to fail. However, my first test is failing while the second is passing.
What am I doing wrong?
You have to put the expectation before the perform_now call.
context "when Model exists" do
it "calls MyModel.fire! with payload" do
expect_any_instance_of(MyModel).to receive(:fire!).with(payload)
RandomJob.perform_now(payload)
end
end
context "when Model does not exist" do
it "does not call MyModel.fire!" do
expect_any_instance_of(MyModel).not_to receive(:fire!)
RandomJob.perform_now(payload)
end
end
I'm quite new to Rspec testing in Rails and I'm trying to test the following:
class Event < ApplicationRecord
def host_details
query ||= User.where(id: self.user_id)
end
def hosting_company
company = host_details.first.company
end
end
I have the following spec but I'm not sure exactly what I'm supposed to be expecting back for the results of the host_details method. I'm using FactoryGirl.
describe "gets information about the host of an event" do
before(:each) do
#event = build(:event)
end
context "host_details" do
it "querys the event data and finds the associated user" do
end
end
context "hosting_company" do
it "gets the company that is hosting the event" do
expect(#event.hosting_company).to eq "Attnd"
end
end
end
I have a controller which has the following method
class <controllername> < ApplicationController
def method
if params["c"]
.....
elsif params["e"]
.....
else
.....
end
end
end
Now, I want to write rspec for the above code.
How can I write separate context for both the params and how will I mention them as a get method.
If I understand your question correctly, you can try approach like this:
RSpec.describe <controllername>, :type => :controller do
describe "GET my_method" do
context "param 'c' is provided"
get :my_method, { "c" => "sample value" }
expect(response).to have_http_status(:success)
end
context "param 'e' is provided"
get :my_method, { "e" => "sample value" }
expect(response).to have_http_status(:success)
end
end
end
Hope it puts you in proper direction.
Good luck!
I want to test the post action of my controller but it fails with an ActiveModel::ForbiddenAttributesError.
require 'spec_helper'
describe HomeController do
describe "POST #create" do
context "with valid attributes" do
it "saves the new feed in the database" do
expect{
post :create, feed: FactoryGirl.attributes_for(:valid_feed)
}.to change(Feed,:count).by(1)
end
end
end
Factory:
FactoryGirl.define do
factory :valid_feed, class: Feed do
title "CRE"
address "http://cre.fm/feed/m4a/"
end
factory :invalid_feed, parent: :valid_feed do |f|
f.address nil
end
end
Controller:
class HomeController < ApplicationController
def index
end
def create
#feed = Feed.new(params[:feed])
if #feed.save
redirect "/"
else
render nothing: true
end
end
end
I checked the params in controller to see if there is something wrong but params[:feed] contains a valid hash.
Did I miss something here?
Yup, you missed something. Rails 4 has enabled strong parameters by default. You'll need to change it to something like this:
class HomeController < ApplicationController
def index
end
def create
#feed = Feed.new(feed_params)
if #feed.save
redirect "/"
else
render nothing: true
end
end
private
def feed_params
params.require(:feed).permit(:allowed, :elements, :of, :feed)
end
end
I have the following class:
I want to ensure the class url is only set once for all instances.
class DataFactory
##url = nil
def initialize()
begin
if ##url.nil?
Rails.logger.debug "Setting url"
##url = MY_CONFIG["my value"]
end
rescue Exception
raise DataFactoryError, "Error!"
end
end
end
I have two tests:
it "should log a message" do
APP_CONFIG = {"my value" => "test"}
Rails.stub(:logger).and_return(logger_mock)
logger_mock.should_receive(:debug).with "Setting url"
t = DataFactory.new
t = nil
end
it "should throw an exception" do
APP_CONFIG = nil
expect {
DataFactory.new
}.to raise_error(DataFactoryError, /Error!/)
end
The problem is the second test never throws an exception as the ##url class variable is still set from the first test when the second test runs.
Even though I have se the instance to nil at the end of the first test garbage collection has not cleared the memory before the second test runs:
Any ideas would be great!
I did hear you could possibly use Class.new but I am not sure how to go about this.
describe DataFactory
before(:each) { DataFactory.class_variable_set :##url, nil }
...
end
Here is an alternative to the accepted answer, which while wouldn't solve your particular example, I'm hoping it might help a few people with a question in the same vein. If the class in question doesn't specify a default value, and remains undefined until set, this seems to work:
describe DataFactory
before(:each) do
DataFactory.remove_class_variable :##url if DataFactory.class_variable_defined? :##url
end
...
end
Works for me with a class with something more like:
def initialize
##url ||= MY_CONFIG["my value"]
...
end