FlexMock and RubyCocoa
Because FlexMock and RubyCocoa disagree about the use of method_missing
, you need to use flexmock
as follows:
flexmock(SomeSubclassOfNSObject)
If the method you want to mock isn’t already defined on SomeSubclassOfNSObject
, you have to define it before mocking it:
class Watcher < OSX::NSObject def observeValueForKeyPath_ofObject_change_context( keyPath, object, change, context) end end
That is ugly and horrible, so I wrote some code to make the class for me. It’s called rubycocoa_flexmock
. It’s used like the following. (I use Shoulda, plus I add some syntactic sugar of my own to FlexMock).
CALLBACK=:observeValueForKeyPath_ofObject_change_context context “change callbacks“ do setup do @watcher = rubycocoa_flexmock(CALLBACK, 4) # DEFINITION @observed = ObservableValueHolder2.alloc.initWithValue(’original‘) end should “include the keypath and changed object“ do add_observer(:watcher => @watcher, :forKeyPath => ‘value‘) during { @observed.value = “hello“ }.behold! { @watcher.should_receive(CALLBACK).once. # USE with(’value‘, @observed, any, any) } end end
rubycocoa_flexmock
can take multiple name/argcount pairs. It’s annoying that you have to give it that information. The problem is that the dependence on an existing method happens within should_receive
, but the number of arguments is only known in the following with
message. And if you never give it a with
, the number of arguments is never known. RubyCocoa is picky about Ruby argument declarations matching exactly what it knows from Objective-C, and I haven’t found a way around that.
The declaration of rubycocoa_flexmock is here. Not the greatest code I’ve ever written, but ’twill serve, ’twill serve.
October 25th, 2008 at 7:31 pm
Did you try any of the other Ruby tools for mocking? If so, were any others more effective?
October 27th, 2008 at 11:24 am
I haven’t.