I am trying to write a test to check a user flow in my application. For that, I need to test a method called is_apple that is in AppleController, AppleController is inherited from FruitsController. I have a method in FruitsController called taste which can be used inside AppleController's is_apple method. The output is the same as expected in the Development and Production environment. But In the Test environment, The method from the FruitsController is undefined in AppleController. I am new to rails testing, I don't know what is potentially causing this issue in my application's test environment.
test_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
class ActiveSupport::TestCase
def setup
puts "starting a test"
post "v1/is_apple", params: {colour: 'red', taste: 'sweet'}
end
end
apple_controller.rb
module V1
class AppleController < FruitsController
def is_apple
return true if taste and params[:colour].eql?('red')
end
end
end
fruits_controller.rb
module V1
class FruitsController < ActionController::API
def taste
# assume
return true
end
end
end
I am using minitest '5.10.3' and rails 6. When I run rails test, am getting undefined_method 'taste' in AppleController. Is there any mistakes in my code? , If yes, How can I achieve the behaviour I wanted. Thanks in advance!
Related
Rails 6.0.0.beta3
rspec 3.8.0
I've just installed rspec-rails on my Rails app. I ran rails g rspec:install and it generated spec/spec_helper.rb, spec/rails_helper.rb and .rspec
The only thing I changed was uncommenting the suggested settings in spec_helper
I'm using gruf to run a gRPC server, instead of a normal HTTP server.
I've also installed gruf-rspec intending to use that to test my gruf controllers.
My gruf controller is at app/rpc/controllers/users_controller.rb following the gruf documentation. Also the compiled protobuf file is at app/rpc/users_services_pb.rb
This is the class signature of the controller:
require 'users_services_pb'
require_relative 'permission_helper'
class UsersController < Gruf::Controllers::Base
bind ::Sil::Rev79::Users::Service
...
end
My problem is that in my test the described_class is nil
Here is my test
# spec/rpc/users_contollers_spec.rb
require 'rails_helper'
require 'users_services_pb'
RSpec.describe 'UsersController' do
describe 'list_users' do
it 'succeeds' do
expect(described_class).not_to be_nil
end
end
end
The test fails.
Why is described_class nil and how can I fix this?
Remove the quotation marks. It shouldn't be a string.
Rspec.describe UsersController do
# insert code
end
Why do i require minitest/autorun instead of test/unit for generating unit test
require 'test/unit'
class Brokened
def uh_oh
"I needs fixing"
end
end
class BrokenedTest < Minitest::Test
def test_uh_of
actual = Brokened.new
assert_equal("I'm all better now", actual.uh_oh)
end
end
Running the above code, interpreter raise warning
You should require 'minitest/autorun' instead
Your code example will end in a NameError: uninitialized constant Minitest.
You have two possibilities:
Use test/unit in combination with Test::Unit::TestCase or
use require 'minitest/autorun' in combination with Minitest::Test.
test/unit is deprecated and it is recommended to use minitest (MiniTest is faster and smaller).
If you switch the test gem you must change perhaps some more things:
replace require "test/unit" with require "minitest/autorun"
replace Test::Unit::TestCase with with Minitest::Test
There is no assert_nothing_raised (details)
assert_raise becomes assert_raises.
perhaps some other issues
You may use require 'minitest' instead require 'minitest/autorun' - you will get no syntax error, but there is also no test execution. If you want to execute tests, you must call them on your own (see minitest-a-test-suite-with-method-level-granularity)
I was stuck with error when i run very simple test with minitest-rails gem.
I have rails 4.1.5 and minitest 5.4.0
rake test:controllers
1) Error:
DashboardController::index action#test_0001_anonymous:
NoMethodError: undefined method get' for #<#<Class:0x00000008e28170>:0x00000008eeb9b8>
test/controllers/dashboard_controller_test.rb:6:inblock (3 levels) in '
Test:
require "test_helper"
describe DashboardController do
context "index action" do
before do
get :index
end
it { must_respond_with :success }
it "must render index view" do
must_render_template :index
end
end
end
My test_helper:
ENV["RAILS_ENV"] = "test"
require File.expand_path("../../config/environment", __FILE__)
require "rails/test_help"
require "minitest/rails"
require "minitest/rails/capybara"
class MiniTest::Spec
class << self
alias :context :describe
end
end
class RequestTest < MiniTest::Spec
include Rails.application.routes.url_helpers
register_spec_type(/request$/, self)
end
class ActionDispatch::IntegrationTest
# Register "request" tests to be handled by IntegrationTest
register_spec_type(/Request( ?Test)?\z/i, self)
end
class ActiveSupport::TestCase
ActiveRecord::Migration.check_pending!
# Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
#
# Note: You'll currently still have to declare fixtures explicitly in integration tests
# -- they do not yet inherit this setting
fixtures :all
# Add more helper methods to be used by all tests here...
extend MiniTest::Spec::DSL
end
There are many things wrong with what you are doing. As I understand it you want to use Minitest's spec DSL in your Rails tests, correct? It looks like you are doing things to accomplish this that you don't need to do. I don't understand why half that code in your test_helper.rb file is there. I also suspect that you have other code doing things that are not being shown.
Here is what I did to reproduce your setup:
$ echo "Creating a new Rails app"
☣ [rails41:rails41] $ rails new undefined_get
☣ [rails41:rails41] $ cd undefined_get/
$ echo "Generate a Dashboard controller"
$ rails g controller dashboard index
$ echo "Add minitest-rails dependencies"
$ echo 'gem "minitest-rails"' >> Gemfile
$ echo 'gem "minitest-rails-capybara"' >> Gemfile
$ bundle install
$ echo "The test runs fine now:"
$ rake test
Run options: --seed 47210
# Running:
.
Finished in 0.457972s, 2.1835 runs/s, 2.1835 assertions/s.
1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
$ echo "Update to your test code and test_helper code"
$ echo "Use whatever editor you want. Not shown here."
$ echo "Now rerun the tests:"
$ rake test
rake aborted!
NoMethodError: undefined method `context' for #<Class:0x007f860258ae50>
The error I get is different than yours. You aliased the method context to describe in your test_helper.rb file, but unfortunately the object you aliased is not in the inheritance chain for the rails test objects. The rails test objects extend Minitest::Spec::DSL, but they do not inherit from Minitest::Spec. So, I am strongly suspicious that the code you provided is indeed producing the results you have presented. That said, here is the code in my test_helper.rb that will run your test:
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require "minitest/rails"
require "minitest/rails/capybara"
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
# Allow context to be used like describe
class << self
alias :context :describe
end
# Add more helper methods to be used by all tests here...
end
This is the standard test_helper.rb with two changes. First, it has the requires for minitest-rails and minitest-rails-capybara. That is all you need to do in order to enable the Minitest spec DSL in your rails tests. Second, it adds the alias for context to describe on ActiveSupport::TestCase, which is the basis for all the rails tests. If you want to add tests that do not inherit from ActiveSupport::TestCase then you can also alias it on Minitest::Spec, but that will not help you use context within your controller tests.
Still here? Okay. So why did your code give you a different error than mine? Likely the test object used for your controller tests isn't ActionController::TestCase. I say that because your error was undefined method get. The get method is something that ActionController::TestCase defines, and is not on Minitest::Spec. So, you somehow messed up your Minitest configuration. A simple way to make sure that your tests are using the correct test objects is to add an additional assertion to your test. Like this:
require "test_helper"
describe DashboardController do
context "index action" do
before do
# Make sure we are using the correct test class
self.class.ancestors.must_include ActionController::TestCase
# Continue with setup
get :index
end
it { must_respond_with :success }
it "must render index view" do
must_render_template :index
end
end
end
If that first assertion fails then you know you have done something wrong in your configuration.
In my Rails app I've added the following files:
app/models/baz.rb
lib/presenters/foo_presenter.rb
lib/presenters/foo_presenter/bar.rb
spec/models/baz_spec.rb
spec/lib/presenters/foo_presenter/bar_spec.rb
The contents of lib/presenters/foo_presenter.rb is something like:
module Presenters
module FooPresenter
def self.render
# do stuff
end
end
end
The contents of lib/presenters/foo_presenter/bar.rb is like:
module Presenters
class FooPresenter::Bar
def baz
# do stuff
end
end
end
The contents of spec/lib/presenters/foo_presenter/bar_spec.rb is like:
require 'spec_helper'
module Presenters::FooPresenter
describe Bar do
# some tests
end
end
Then I have a spec file in spec/models/baz_spec.rb:
require 'spec_helper'
describe Baz do
it 'works' do
Presenters::FooPresenter.render
end
end
(The contents of app/models/baz.rb is not relevant to this issue)
The problem is when I run rspec spec/models/baz_spec.rb it works fine without spork, but when spork is running, I get an error like:
NameError: undefined method `render' for Presenters::FooPresenter:Module
I traced through the code a bit and noticed that when rspec loads spec/lib/presenters/foo_presenter/bar_spec.rb it causes Rails to autoload lib/presenters/foo_presenter/bar.rb and so at that point Presenters::FooPresenter::Bar is loaded, but then when baz_spec.rb runs, lib/presenters/foo_presenter.rb has never been loaded and thus the exception. But this only happens if spork is running. The quick fix was to require 'foo_presenter' in a file in config/initializers, but is there a cleaner solution that doesn't need the explicit require? My guess is the issue here is that Rails doesn't autoload lib/presenters/foo_presenter.rb because Presenters::FooPresenter has already been defined by bar_spec.rb.
A co-worker and I were faced with this problem today and we eventually found we needed Spork to reload the classes on every run. We used the each_run() method to do this:
Spork.each_run do
Dir[Rails.root.join("app/classes/**/*.rb")].each {|f| require f}
end
I'm trying to write a custom Rake task to perform some tests for a class placed in the lib directory. This works for basic tests not requiring any models, but I need to actually test using some models. It's my first foray into more advanced rake usage and after going through some other hurdles I've got stuck on getting a ConnectionNotEstablished error.
Here's the rake task:
Rake::TestTask.new(:test => 'db:test:prepare') do |test|
test.libs << 'test/sync'
test.test_files = Dir['test/sync/*_test.rb']
test.verbose = true
end
Here's the test that raise the ConnectionNotEstablished exception:
require 'rubygems'
require 'app/models/city'
require 'foo'
require 'test/unit'
class SyncTest < Test::Unit::TestCase
##sync = Foo::Sync.new('test')
def test_cities
assert City.all.size == 2 # the exception is raised at this point
##sync.cities
assert City.all.size == 102
end
end
Here's a unit test that is actually working:
require 'test_helper'
class CityTest < ActiveSupport::TestCase
test "the truth" do
assert City.all.size == 2
end
end
I've tried using derive my test class from ActiveSupport::TestCase instead of Test::Unit::TestCase but it still raise a ConnectionNotEstablished error. I'm certainly doing something wrong, can anyone find what or tell of a better way to do that?
I've finally found out what the problem was, I've replaced the two first require call by:
require 'test_helper'
and added the test directory to the TestTask's libs attribute:
test.libs << 'test'