Can't access inherited method in test environment Rails - ruby-on-rails

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

rspec `described_class` is `nil`

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 need to use minitest/autorun?

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)

Minitest - NoMethodError: undefined method `get'

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.

Rails autoloading behaves strangely in RSpec with modules and subclasses with spork

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

ConnectionNotEstablished error in custom TestTask

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'

Resources