Using RSpec with MacRuby, Part 2
Update 11/Dec/2009: The described solution doesn't work with MacRuby 0.5 as noted by Matt Aimonetti in the comments of the first part.
This is the second part of our small series about MacRuby and RSpec. In the first part, we have added RSpec to the example project MacRubyTwitterMG, did a small patch to make it run and defined the first two specs. Now we want to define some more specs and learn how to use mock objects:
- The next spec shall test the method refresh and looks like this:
For several reasons we do not really want to connect to Twitter here, so we try to mock the object @twitterEngine.describe "#refresh" do it 'should refresh the tweets when username and password are given' do @main_controller.username = "ashtom" @main_controller.password = "secret" @twitterEngine.should_receive(:setUsername).with("ashtom", password:"secret") @twitterEngine.should_receive(:getFollowedTimelineSinceID) @main_controller.refresh(nil) end end
The problem with this code is that MacRuby does not know the class MGTwitterEngine while running the specs from the command-line, because we have added all of its Objective-C source files directly to our Xcode project. A possible solution might be to create a framework for MGTwitterEngine, so let's try this.before :each do @twitterEngine = mock("MGTwitterEngine") @twitterEngine.stub!(:initWithDelegate).and_return(@twitterEngine) MGTwitterEngine.stub!(:alloc).and_return(@twitterEngine) end - Select File > New Project..., then choose Cocoa Framework and continue with Choose.... Enter MGTwitterEngineFramework as the name of the new framework and put it into the Vendor directory which we've already created.

- Drag the group Vendor > MGTwitterEngine from the project MacRubyTwitterMG to the newly created project.

- Right-click the target MGTwitterEngineFramework, choose Get Info and change the following settings:
- Close the inspector.
- Select x86_64 as the active architecture, then hit Build & Go.
- Now we change the file
spec_helper.rbin the MacRubyTwitterMG project to include the new framework:framework File.expand_path(File.dirname(__FILE__) + '/../Vendor/MGTwitterEngineFramework/build/Debug/MGTwitterEngineFramework.framework') - Back to the spec, we need to call the method awakeFromNib to initialize the instance of MGTwitterEngine:
As awakeFromNib is accessing the member @timelineTableView (which is an IBOutlet connected to the table view) we need to mock it as well:before :each do # ... @main_controller.awakeFromNib endbefore :each do # ... @timelineTableView = mock("NSTableView") @timelineTableView.stub!(:dataSource=) @main_controller.timelineTableView = @timelineTableView @main_controller.awakeFromNib end - We run the specs:
$ macruby Spec/Controllers/MainControllerSpec.rb ... Finished in 0.078637 seconds 3 examples, 0 failures
- Done.
The complete code is (as always) available at GitHub.
Aftermath
After having defined some more specs I now get the following warning:
~/Projects/MacRubyTwitterMG/Vendor/RSpec/lib/spec/mocks/proxy.rb:201: warning: removing pure Objective-C method `proxied_by_rspec__alloc' may cause serious problemThis seems to be related to the stub of MGTwitterEngine.alloc, but so far I've found no way to prevent the warning. If you have a solution, please post a comment.
Keywords: mac, programming, ruby
Keywords
- blog (1)
- iphone (4)
- mac (4)
- programming (5)
- ruby (6)
- ruby on rails (2)
- snippet (1)
- statistics (1)


Comments