rr gem assert_received equivalent in mocha gem - ruby-on-rails

Now I use rr gem to stub Project model count method, and then I replicate index action to check the count method is called or not. I'm planning to use mocha gem but I don't figure out what is the equivalent of assert_received method in mocha gem. Following code is one of the example of my tests.
require 'test_helper'
class ProjectsControllerTest < ActionController::TestCase
context "on GET to index" do
setup do
stub(Project).count { 30000 }
get :index
end
should "load up the number of gems, users, and downloads" do
assert_received(Project) { |subject| subject.count }
end
end
end

require 'test_helper'
class ProjectsControllerTest < ActionController::TestCase
context "on GET to index" do
setup do
Project.stubs(:count).returns(30000)
end
should "load up the number of gems, users, and downloads" do
Project.expects(:count).returns(30000)
get :index
end
end
end
Hope this can help, and here is the mocha API.

Related

Rails Test w/ Minitest Reporter - NoMethodError: undefined method + ActionController::UrlGenerationError: No route matches

I am learning Rails and very new to testing but so far I've managed to build something with minimal errors. However, the issue I am running into is that my tests are complaining for methods that cannot be found and no route matching.
To my understanding tests should be run frequently based Hartl's - Railstutorial 3.3. Many StackO threads and online articles seem to pertain to utilizing test suites I don't use like RSpec, etc...so the test configurations are confusing. My testing suite is set up similiar to Hartl's - Railstutorial 3.3 and below are the gems loaded for testing.
gem 'better_errors', '~> 2.1.1'
gem 'binding_of_caller'
gem 'minitest-reporters', '1.0.5'
gem 'mini_backtrace', '0.1.3'
gem 'guard-minitest', '2.3.1'
gem 'ruby-prof'
NoMethodError: undefined method
Error: (_I have two error similar errors to below_)
ServicesControllerTest#test_should_get_index:
NoMethodError: undefined method 'services' for nil:NilClass
app/controllers/services_controller.rb:6:in 'index'
test/controllers/services_controller_test.rb:9:in 'block in <class:ServicesControllerTest>"
Services Controller
def index
#services = current_tech.services
end
services_controller_test.rb
require 'test_helper'
class ServicesControllerTest < ActionController::TestCase
setup do
#service = services(:one)
end
test "should get index" do
get :index
assert_response :success
assert_not_nil assigns(:services)
end
end
I believe the reason I am receiving this error is because of Devise.
If I were to setup the following index action below, the test will pass.
def index
#services = Tech.first.services
end
How do I correct this so that this test passes?
ActionController::UrlGenerationError: No route matches {:action=>"show", :controller=>"tech"}
Error:
CarsControllerTest#test_should_get_show:
ActionController::UrlGenerationError: No route matches {:action=>"show", :controller=>"cars"}
test/controllers/cars_controller_test.rb:5:in `block in <class:CarsControllerTest>
Rake routes pertaining to cars
tech_cars POST - /techs/:tech_id/cars(.:format) - cars#create
car GET - /cars/:id(.:format) - cars#show
Routes
Rails.application.routes.draw do
devise_for :customers, controllers: { sessions: 'customers/sessions' }
devise_for :techs, controllers: { sessions: 'techs/sessions' }
resources :techs, :only => [:index, :show], shallow: true do
resources :cars, only: [:show, :create]
end
resources :services, :garages
root "home#index"
end
cars_controller.rb
class CarsController < ApplicationController
before_action :set_car
def show
#garage = Garage.find(params[:id])
#tech = #tech.service.car.id
end
def create
#garage = Garage.create(tech_first_name: #car.service.tech.first_name,
customer_id: current_customer.id,
customer_street_address: current_customer.street_address,
customer_city: current_customer.city,
customer_state: current_customer.state,
customer_zip_code: current_customer.zip_cod)
if #garage.save
redirect_to techs_path, notice: "Working"
else
redirect_to techs_path, notice: "Uh oh, flat tire"
end
end
private
def set_car
#car = Car.find(params[:id])
end
def car_params
params.permit(:service_name, :garage_photo)
end
end
cars_controller_test.rb
require 'test_helper'
class CarControllerTest < ActionController::TestCase
test "should get show" do
get :show
assert_response :success
end
end
cars.html.erb (only links on page)
<%= button_to 'View Garage', tech_cars_path(tech_id: #car.service.tech.id, id: #car) %>
<%= link_to 'Back to tech', tech_path(#car.service.tech.id) %>
As you may gather, I am building a Garage not a Car object within the Cars controller. Would this be a problem for tests? My application functions fine as is. On a side note, I am also having difficulty trying to associate car_params strong params for instance variables but that's another StackO post.
*test/test_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require "minitest/reporters"
Minitest::Reporters.use!
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
# Add more helper methods to be used by all tests here...
end
class ActionController::TestCase
include Devise::TestHelpers
end
Is there something I am missing or haven't configured correctly?
Please know my application appears to be working fine, it's just I would like to suppress these tests errors.
Please advise on how to get these test errors to pass.
Thanks
First issue: Your feeling is correct. Devise comes with Devise::TestHelpers which you've mixed into ActionController::TestCase in your test helper file. One of the methods it provides is sign_in which lets you spoof a logged in user as part of your test. Assuming you've got a model called Tech and you're following standard Rails conventions, you'll need to add something like:
sign_in techs(:some_tech)
to either your setup block or directly into your test body before the call to get :index. That will ensure that current_tech returns something non-nil and remove the immediate NoMethodError.
Second issue: Your :show action expects to receive the ID of a known Car as part of the URL. Replace your current invocation of the controller with:
require 'test_helper'
class CarControllerTest < ActionController::TestCase
setup do
#car = cars(:some_car)
end
test "should get show" do
get :show, id: #car.id
assert_response :success
end
end

stripe-ruby-mock gem with Minitest

I am new to testing. I am trying to use stripe-ruby-mock gem with minitest.
In the stripe-ruby-mock docs they describe a dummy example in Rspec that I am trying to translate to minitest:
require 'stripe_mock'
describe MyApp do
let(:stripe_helper) { StripeMock.create_test_helper }
before { StripeMock.start }
after { StripeMock.stop }
it "creates a stripe customer" do
# This doesn't touch stripe's servers nor the internet!
customer = Stripe::Customer.create({
email: 'johnny#appleseed.com',
card: stripe_helper.generate_card_token
})
expect(customer.email).to eq('johnny#appleseed.com')
end
end
My translation to minitest
require 'test_helper'
require 'stripe_mock'
class SuccessfulCustomerCreationTest < ActionDispatch::IntegrationTest
describe 'create customer' do
def stripe_helper
StripeMock.create_test_helper
end
before do
StripeMock.start
end
after do
StripeMock.stop
end
test "creates a stripe customer" do
customer = Stripe::Customer.create({
email: "koko#koko.com",
card: stripe_helper.generate_card_token
})
assert_equal customer.email, "koko#koko.com"
end
end
end
The error
NoMethodError: undefined method `describe' for SuccessfulPurchaseTest:Class
I consulted the minitest docs to make sure describe wasn't specific to Rspec but it turns out it is also used in minitest. I am guessing the implementation isn't done properly. Any help appreciated.
Hi I'm mostly an Rspec guy but I think you're issue is that you are using and integration test case when you should be using an unit test case. Try the following instead
class SuccessfulCustomerCreationTest < MiniTest::Unit::TestCase
I think you are mixing things. Check Minitest page on sections Unit tests and Specs.
I think what you need is the following:
require 'test_helper'
require 'stripe_mock'
class SuccessfulCustomerCreationTest < Minitest::Test
def stripe_helper
StripeMock.create_test_helper
end
def setup
StripeMock.start
end
def teardown
StripeMock.stop
end
test "creates a stripe customer" do
customer = Stripe::Customer.create({
email: "koko#koko.com",
card: stripe_helper.generate_card_token
})
assert_equal customer.email, "koko#koko.com"
end
end
Or if you want use the Spec syntax. Hope this helps someone.
you want to require:
require 'spec_helper'
for rspec example.

Rails: Moving a helper method form a test to test_helper.rb

I am trying to move a helper method from a controller test to the test_helper.rb:
# example_controller_test.rb
require 'test_helper'
class ExampleControllerTest < ActionController::TestCase
should 'get index' do
turn_off_authorization
get :show
assert_response :success
end
end
# test_helper.rb
class ActionController::TestCase
def turn_off_authorization
ApplicationController.any_instance
.expects(:authorize_action!)
.returns(true)
end
end
However, I'm getting an error:
NameError: undefined local variable or method `turn_off_authorization' for #<ExampleControllerTest:0x000000067d6080>
What am I doing wrong?
Turns out that I had to wrap the helper method into a module:
# test_helper.rb
class ActionController::TestCase
module CheatWithAuth do
def turn_off_authorization
# some code goes here
end
end
include CheatWithAuth
end
I still don't know why the original version didn't work.
The idea came from another answer:
How do I write a helper for an integration test in Rails?
Edit: Another solution just came from my friend:
# test_helper.rb
class ActiveSupport::TestCase
def turn_off_authorization
# some code goes here
end
end
Note that ActiveSupport::TestCase (not ActionController::TestCase) is being used here.

How do you "nest" or "group" Test::Unit tests?

RSpec has:
describe "the user" do
before(:each) do
#user = Factory :user
end
it "should have access" do
#user.should ...
end
end
How would you group tests like that with Test::Unit? For example, in my controller test, I want to test the controller when a user is signed in and when nobody is signed in.
You can achieve something similar through classes. Probably someone will say this is horrible but it does allow you to separate tests within one file:
class MySuperTest < ActiveSupport::TestCase
test "something general" do
assert true
end
class MyMethodTests < ActiveSupport::TestCase
setup do
#variable = something
end
test "my method" do
assert object.my_method
end
end
end
Test::Unit, to my knowledge, does not support test contexts. However, the gem contest adds support for context blocks.
Shoulda https://github.com/thoughtbot/shoulda although it looks like they've now made the context-related code into a separate gem: https://github.com/thoughtbot/shoulda-context
Using shoulda-context:
In your Gemfile:
gem "shoulda-context"
And in your test files you can do things like (notice the should instead of test:
class UsersControllerTest < ActionDispatch::IntegrationTest
context 'Logged out user' do
should "get current user" do
get api_current_user_url
assert_response :success
assert_equal response.body, "{}"
end
end
end

Test (with RSpec) a controller outside of a Rails environment

I'm creating a gem that will generate a controller for the Rails app that will use it. It's been a trial and error process for me when trying to test a controller. When testing models, it's been pretty easy, but when testing controllers, ActionController::TestUnit is not included (as described here). I've tried requiring it, and all similar sounding stuff in Rails but it hasn't worked.
What would I need to require in the spec_helper to get the test to work?
Thanks!
Here's an example of a working standalone Test::Unit test with a simple controller under test included.. Maybe there's some parts here that you need to transfer over to your rspec code.
require 'rubygems'
require 'test/unit'
require 'active_support'
require 'active_support/test_case'
require 'action_controller'
require 'action_controller/test_process'
class UnderTestController < ActionController::Base
def index
render :text => 'OK'
end
end
ActionController::Routing::Routes.draw {|map| map.resources :under_test }
class MyTest < ActionController::TestCase
def setup
#controller = UnderTestController.new
#request = ActionController::TestRequest.new
#response = ActionController::TestResponse.new
end
test "should succeed" do
get :index
assert_response :success
end
end

Resources