So I'm trying to figure out a way of stubbing a controller method in rspec for a Sinatra app. The main reason for this is to test the logical flow of the application and to make sure it calls the necessary functions when certain conditions are met. So, in essence, I want to be able to do something like
controller.should_receive(:fancy_method).and_return("This is a string")
What I'm having difficulty doing is accessing the controller instance within the sinatra app. I am able to override the current functions using a class_eval on the sinatra controller class, but I'd love to assert that these functions actually run.
Anyone have any advice?
Thanks.
Dan, I believe what you really want is to just test the controller actions. From a tester's perspective you shouldn't really care about what it actually called but rather for the output, given a specific input and maybe some other special conditions (that is mocking or stubbing other classes) (1).
You can check the official documentation for Sinatra + Rack::Test or this blog post from devver.net.
(1) : If your controller pages are calling some other classes (models, services, etc) you could mock these instead and put expectations on them. For example :
SomeClass.should_receive(:msg).with(:arg).and_return(:special_value)
Some more info for mocking (with RSpec in this exmaple) can be found on the RSpec documentation pages.
Related
I'm working on a project in Ruby on Rails. We have a controller action that uses a module within a gem. This gem isn't finished yet and it isn't on the file system.
I was told to mock the module in order to test the controller. Is there a way to test this without the actual gem? Would mocking the 'require' calls work?
We are currently using Mocha for Mocking and Stubbing.
There is a way to mock the imports in python. Maybe there is a similar answer to mocking the requires in ruby.
How to mock an import
Or please let me know what would be the best way to handle this.
Update: The person who told me to mock it, suggested adding a stub file, but that would require adding test code to the controller and I don't want to do that.
Update 2: The controller uses methods declared in the Module.
If you are writing tests to mock the method calls, they would fail. For example,
controller.should_receive(:method_in_non_existent_module).with(args) #=> errors
In a correct Red->Green TDD scenario , this is alright because the next step would be to require the gem/file, include the module and add the method call in the controller and make the test pass. But you'll not be able to make the tests pass since you can't require the file because it doesn't exist yet.
May be the developer who asked you to mock the method meant to do so not in your tests, but in your actual code. For example, he's writing a gem 'dongle-jokes' which has a method that gets the most popular dongle joke from the most recent tech conference. He doesn't want the gem to be a blocker for you to finish the controller and the views so he asks you to use a dummy interface that spits out a dummy response.
Write the tests that fail
Add a file lib/dongle-jokes.rb
Add the following to that file.
module DongleJokes
def joke
"Dongle jokes aren't funny!"
end
end
Require the file and include the module, use the method in the controller.
The test should pass now. You can remove lib/dongle-jokes.rb when you start using the actual gem.
If you're working in Rails you shouldn't need to add a require to the controller anyway, as when you add the gem to your gemfile it will be required automatically on Rails startup.
What your colleague most likely meant was that you should stub the module itself. Are you using rspec for your tests? If so you should be able to use stub_const. Let's say the module is called Payments. You can then write test code like the following:
before do
stub_const("Payments", stub)
Payments.stub(process: "payments successful")
end
I just completed writing a detailed rspec capybara integration and unit tests for Rails app, which includes mocking Omniauth (twitter) login, filling in forms, data validations, etc. However, I am wondering whether there is a need to write a separate controller or functional test.
Would appreciate your input and any links to further readings etc.
I'll play devil's advocate here, since I know I'm probably in the minority with this opinion: I actually prefer to do exceedingly thorough controller testing. A few reasons:
1) I find it easier to systematically test every path and outcome at the controller level than at the integration test level. My integration tests are primarily just happy-paths, and some of the more common error paths.
2) A lot of potential security issues occur at the controller level. Thorough testing helps me ensure that nothing malicious can get through to my model logic.
3) This is subjective, but it really forces me to think about some of the long-tail paths that my application might go through. What if someone tries to for an invalid password reset token into the URL? Controller testing ensures that I consider all options.
4) Unlike integration tests, they're fairly straight-forward to test. Each action is just a ruby method!
Personally, I think if your request (integration) spec is exercising all code paths you're covered. Ryan Bates has a great Railscast about how he tests here: http://railscasts.com/episodes/275-how-i-test?autoplay=true and about 5:05 in he says a similar thing. Like you I like to write integration tests rather than controller specs. Most of the time controllers simply front CRUD type operations anyway (especially if you're careful about keeping domain logic out of the controller), so all you're testing is the scaffolding.
We have a isolated test automation team responsible for automating only watir+cucumber functional test cases. Their code base is not attached with the rails app that other developers are working on, but kept separate. We have automated several test cases so far, and now what problem we have is, some (watir/cucumber specs)test cases require some data to be preexist into db, so it(testcase) should focus only on the problem stmt, and not creating any data-require itself.
Example, say if it has to check whether rating is working for a post, it requires a post object should preexist and it just checks rating. And not creating 1st post object and then checking its rating.
What are the best approaches here? Like we have fixtures and factory-girl for rails unit testing, what is there for cucumber specs? Or Shall we make use of features only here? These testers may not have idea of all models that exist, do they be aware of them so to make use of fixtures by calling Rails-Model interface.
My idea was, when we write feature file, it should not point or talk about any Model which looks meta stuff. Watir/specs test cases should only be aware of "Web-application"/browser only as the interface to talk/deal with the application. They should not know any other interface(fixture/Models). Hence they should create their own data on their own, by making use of the single interface they know.
Again, what I want to know that, is there any ruby lib/code, given table names, column names, and values(all most like fixtures yml), along with db parameters. It will simply insert them into db, without context of rails environment. And so testers those are having their environment isolated from rails web developers would able to work on their own. Rails fixtures, or factory girls seem to be well coupled with rails. Or am I incorrect?
Like Chirantan said you could use Factory girl with cucumber.
As require your factories in test unit or RSpec, you can do the same in the cucumber's env.rb file or any custom config file.
http://robots.thoughtbot.com/post/284805810/gimme-three-steps
http://www.claytonlz.com/2010/03/zero-to-tested-with-cucumber-and-factory-girl/
http://www.andhapp.com/blog/2009/11/07/using-factory_girl-with-cucumber/
When using cucumber, the Given statement sets the test situation up:
Given I have a basic user with a password
and the When statement triggers the test:
When the user logs in
and the Then statement checks the test results
Then they see the basic menu
The data gets loaded in the Given statement.
I'm writing a plugin for Cinch (the IRC bot), and trying to write some RSpec tests for it.
However, I'm trying to get to grips with RSpec, and mocking out the external dependencies of this plugin. I want to test two different things for now - that it says hello to people, and that it keeps track of who it's said hello to.
So I've got a method, say_hello, which takes a Cinch::Message. What's the easiest way to mock this particular class? I'm used to Mockito and Java, so I'm used to making a mock of a particular class.
How can I make a mock of Cinch::Message? In my first test, I want to assert that the reply method is called on that message. In the next one, I just want it to respond like a Cinch::Message would, as I only care about the tracking the class does, not the interaction with the message.
I've only just started out with RSpec, so maybe I'm missing something fundamental. Should I be using a mock? A stub?
Thanks!
First of all documentation would be a nice start point, see: https://www.relishapp.com/rspec/rspec-mocks/v/2-11/docs/message-expectations
..and this is how your test could look:
it 'should call #reply on the message'
message = double('cinch message')
message.should_receive(:reply)
object_under_test.say_hello(message)
end
I'm sick of writing out the same controller specs each time I make a new controller. I know I can use the scaffold generator, but there are enough little things I have to change that it usually doesn't save me much time.
Are there any projects/tools out there that provide some sort of base set of specs and/or a DSL to make this easier?
I've never found that any two REST controllers I wanted to write had similar enough interfaces that the tests were at all similar (and generally, I recommend Cucumber, not controller specs).
Something like inherited_resources or Rails 3's respond_with is very useful for writing the controllers, but I'm not sure about the tests.
I use the decent_exposure gem.