Posts

Showing posts with the label Mocking

When Your Mocks Burst into Flames

So yesterday Leah and I were working on SudokuScanner -- a cool little site that will, when it's released, allow you to upload images of Sudoku boards and get a solution. All of a sudden, our mocks and stubs went totally batshit. One minute she and I were happily writing some tests, making them pass, refactoring, checking in, etc... and then, we got a bunch of failures. OK, no problem -- we must have busted something with our latest change. The failure was a mock expectations error: UserMailer expected to receive a call to deliver_activation but did not receive it. So we went over to the failing spec and... There was no expectation on UserMailer anywhere in the spec. That's bad. Ran the spec by itself and it passes. Yep - not so good. Reverse the order that the specs run in (spec --reverse) and a different number of specs fail, but still with the same expectation failure. And of course these new specs all pass on their own. And have no reference to UserMailer anywher...

Sprinkle Some Integration Tests into a Mock Heavy Test Suite

I like mocks and stubs and I use them liberally in my tests. This practice, however, is not without danger: If my models, views, and controllers are all tested in isolation then how will I know if a model change busts a controller or a view? Here's something I like to drop in at the end of every controller spec: 1 2 3 4 5 6 7 8 9 10 11 12 describe JerkStoreController , " with views integrated and real objects " do integrate_views it " should render the page without blowing up " do store = JerkStore .create!( :name => " Costanza's house of bargins " ) store.products << Jerk .create!( :name => " Puddy " ) << Jerk .create!( :name => " Newman " ) << Jerk .create!( :name => " Steinbrenner " ) post :show , :id => store.id end end Not a mock or a stub as far as the eye can see and I'm even integrating views. No...

If you use Mocha and RSpec then read this

I like RSpec, but I'm not a huge fan of it's built in mocking framework. So, when I have the choice, I swap it out for Mocha. However, I really miss mock_model. If you haven't used it, mock_model is an RSpec method where you pass in an ActiveRecord object and it stubs out a whole bunch AR magic so you don't have to. This is crazy useful when testing controllers because when you controller has a line like this: redirect_to(@model) I don't want to dig through a ton of Rails code to figure out what I need to stub on this model, I just want it to work. But I just found out that Mislav Marohnić has written a plugin that implements mock_model for Mocha -- so now I can get the best of both worlds. You can find it here: http://github.com/mislav/rspec-rails-mocha Thanks Mislav.

Disconnecting RSpec from the Database

Recently I spent some time away from RSpec and I did miss it, but one thing especially liked about the testing framework I lived in for 10 months was that it had two ways to test anything you liked: One that hit the database and one that did not. We used UnitRecord to disconnect unit tests from the database (I should mention that we defined unit tests as tests that didn't hit the db and functional tests as those that did). So the vast majority of our tests didn't really need to hit the db and ran very fast. Sometimes we wanted or needed to hit the db and we did (only occasionally in model tests, more often in controller tests, and we kept logic out of the view and only tested views at the Selenium level). It was pretty cool and I'd like to thank the team who set it up before I got there. There's been a lot of talk about whether model, view, or controller tests should hit the db but I've found that there's enough exceptions that it's worth just saying that...

Mocking Backticks and Other Kernel Methods

There's a bunch of places in our build where we need to execute a system command (such as running sqlplus) but often times we've found that the command fails and our build happily churns away. It's pretty easy to check the result of system command with $?.success? but we have to remember to do that everywhere... So that means it's time to extract a method. Here's what Kurtis and I came up with: module DatabaseHelper def self.command_runner(command) output = `#{command}` puts output fail unless $?.success? fail if output.include? "ERROR" output end end So you pass in a command as a string and the command runner: runs the command prints out the output fails if the return code is bad fails if the output includes "ERROR" (useful when running database imports with sqlplus) and returns the output just to be a good citizen So that's cool but when I started to write the module I thought "Hey, I can test this." Which is...

Using OpenStruct to Enhance Your Mocks

So I use RSpec's built in mocking framework for my mocking/stubbing and it works quite well. I sent up a mock like so: mock_active_record_instance = mock("give it a name here, but probably a better one than this") and put some expectations on it like so: mock_active_record_instance.should_receive(:id).and_return(1) but some calls to the mock I don't care about so I can stub them out like so: mock_active_record_instance.stub!(:name). and_return("Arthur, King of the Britons") If I don't need it to return anything I can leave off the and_return and it will return nil. But it's tedious to do that. Lately I tend to use OpenStructs as my mocks like so: mock_active_record_instance = OpenStruct.new mock_active_record_instance.should_receive(:id).and_return(1) Now here's what's cool about that: My spec(test) will fail if the expectation of a call to id isn't met, but any other calls will be ignored (and nil returned). If I had made mock_a...