Defining stub methods in test_helper? - ruby-on-rails

Can I define all of my stub methods at one place instead of defining them in each test case?
For example i have this piece of code
SocialNetworks::Facebook.any_instance.stubs(:update_status).returns(true)
in multiple test cases. But if I move it in test_helper.rb file then running test cases won't work.
Does mocha gem allowed to place these stubs at one place?
I am using rails Minitest for testing rails app. And mocha gem for
stubing and mocking.

You can do that in setup callback, like:
class YourTest < ActiveSupport::TestCase
setup do
SocialNetworks::Facebook.any_instance.stubs(:update_status).returns(true)
end
end
setup is called before each test case.

Related

How do I use the normal controller test assertions in Minitest Spec DSL

I usually write my specs in RSpec but I use Minitest too.
Recently I learnt that there is a minitest dsl that could read like RSpec. They call it Minitest::Spec. I have checked it out and I think I like it. The gem 'minitest-rails' makes the setup configuration easy. There is however one limitation I have faced and that is in the integration specs. What is the equivalent for assertions like assert_response, assert_no_difference, and assert_template?
I have seen an answer. It turned out that I got them in the very gem that supplied the test expectations. I looked into the source code of the minitest/rails/controller.rb and I saw the simple way those expectations were implemented is by aliasing the real minitest assertions. Here is my find
class ActionController::TestCase # :nodoc:
alias :must_respond_with :assert_response
alias :must_redirect_to :assert_redirected_to
alias :must_render_template :assert_template
alias :must_select :assert_select
alias :must_select_email :assert_select_email
alias :must_select_encoded :assert_select_encoded
end

How to automatically skip callbacks in all unit tests but not in any integration tests

I use Rspec for testing under Rails 4.
I'd like to configure Rspec so that all my unit tests automatically run without callbacks, but all my integration tests run as Rails intended -- with all the same callbacks as you get in production and development.
Is this possible?
I can think of long-winded solution that involve writing conditional logic into my actual callbacks, but not elegant solutions that involve configuring Rspec.
You can replace your callback methods with test doubles when your unit tests run, as described in https://relishapp.com/rspec/rspec-mocks/v/3-0/docs/message-expectations/allow-a-message-on-any-instance-of-a-class
For example, if you had the following class:
def Foo < ActiveRecord::Base
before_create :my_callback
...
end
you could stub the callback as follows:
allow_any_instance_of(Foo).to receive(:my_callback)

NoMethodError: undefined method `stub' for ModuleX:Module

Using Mocha, I am trying to mock a controller method that calls a module method.
This is for an integration test.
Example:
class Controller < ApplicationController
def method1
response = Module1.method2(...
My steps so far:
Added mocha to gemfile
Added require 'mocha/mini_test' to the very bottom of my
test_helper.rb
Tried this code in my integration test before sending a post to my controller:
Module1.stub(:method2).returns(:true)
post "controller/method1"
And got this error:
NoMethodError: undefined method 'stub' for Module1:Module
Is it possible to stub method2?
EDIT: So the main fix is that the method is 'stubs' not 'stub'. I'm still having trouble mocking this dang Module though.
EDIT: Rails and MiniTest just call the module method even after I've stubbed it. Is it possible that Rails is overwriting my stub?
class Test < ActionDispatch::IntegrationTest
test "test do
Module1.stubs(:method2).returns(:true)
post "controller/method1"
This test leads to error inside method2 bc no parameters were passed in. The test is behaving as if the method was not stubbed.
try .stubs with an s.
The stubnotation is to build a stub you'lle use later on.
Add an s when you stub a method directly on something.
regarding your test you may want a
Module1.expects(:method2)
but the stub should work anyway. Rails would not overrite your stub, maybe you test_helper does, but i'm quite sure it is more a syntax thing.
Paste your real code and test because here right know it's kind of difficult and can be anything... a callback preveting the method to be called, the test syntax, ...
for me this was caused by not adding require 'minitest/mock' to my test_helper.rb

Rails 2.3 and minitest

I would like to try minitest with an existing Rails 2.3.14 application. I already tried several approaches but none of them seem to work.
It essentially boils down to this. When I add minitest to the Gemfile, all tests I run with bundle exec rake test are NOT executed with minitest.
The problem is that most of the test cases extend the ActiveSupport::Testcase or ActionController::Testcase (which extends ActiveSupport::TestCase).
By looking at the code of this class I saw that it already (somehow) suppports MiniTest:
class TestCase < ::Test::Unit::TestCase
if defined? MiniTest
Assertion = MiniTest::Assertion
alias_method :method_name, :name if method_defined? :name
alias_method :method_name, :__name__ if method_defined? :__name__
else
...
end
(see https://github.com/rails/rails/blob/2-3-stable/activesupport/lib/active_support/test_case.rb for complete code)
My question here is:
Is it somehow possible to use minitest instead of test::unit in Rails 2.3 without having to extend (MiniTest::Unit::TestCase)
Any testing framework is made of two things, a way to define and run tests (call this the test runner) and an assertion framework.
Looking at ActiveSupport it seems that if MiniTest is defined at all, running the rails Unit test runner will default to using MiniTest's assertions classes. This means you get to use Minitest's assertion syntax.
Getting MiniTest defined should just be a case of requiring 'minitest\unit'.
However if you want to use the runners, then you need to derive from the MniTest framework test fixture base classes.
There is a step by step walkthrough in railscasts for setting it up yourself.
It boils down to:
Remove test_unit from your config/applications.rb
Add the minitest gem to your gem file "Gemfile"
Setup the environment in a helper file you can include into your tests
Add a rake task to run the tests. (/lib/tasks/minitest.rake)
Railscasts has the details.
If you don't want to change your existing tests to do that.. then you have to monkey patch Test::Unit to redefine TestCase to either be the chosen MiniTest base class or something that derives from one. This is the approach that this gem takes and may give you some ideas on how best to go about that.
The other solution is to do a search/replace through your code to switch the base classes of the test cases.
I hope this helps.
I Updated my answer and remove the following as out of date:
minitest-rails has rightly been pointed out as it works for Rails 3.1 only.
This gem seems to be old (26th March 2009) but it may help. Check the source code if you need hints to do something similar.

Where to put common Unit Test code in ruby on rails environment?

Using Rails 3.0, I have a small bit of code that I seem to be calling in all my Unit tests.
Is there a common place to put shared unit test code that won't be incorporated into both unit and functional tests? I'd rather ONLY incorporate it into the needed files, just the unit tests.
I'm new to testing practices in general. Is it common in Rails to test validations (for example, test: validates_presence_of :name)? Most of my functions that test validations on a model are all basically the same (just swap in and out correct fixture and attribute name). Doesn't seem very DRY. Looking for a way to refactor.
Thanks.
You can place the code in the test/test_helper.rb file.
You should already find a code fragment that looks like this
class ActiveSupport::TestCase
self.use_transactional_fixtures = true
self.use_instantiated_fixtures = false
end
If the code should be used in all your tests, you can add your methods in the ActiveSupport::TestCase class. Otherwise, wrap them into a Module and mix the module where required.
It's a good practice to test validations not to test the validation itself (the validates_presence_of macro is already tested in the Rails codebase), but to make sure chances in your code don't affect your class business.
For instance, there might be validation which needs to be triggered only in specific events. Or you might want to make sure no one removed your super-secret validation on that specific model.
If you want to test your model validations, I encourage you to check out shoulda. Shoulda provides several handy methods to test your validations.
class PostTest < ActiveSupport::TestCase
should belong_to(:user)
should validates_presence_of(:id)
end

Resources