require 'osx/cocoa' include OSX require 'test/unit' require 'shoulda' require 'flexmock/test_unit' # This file contains methods I find useful when using mocks. # These methods are used to change the flow of control so that the # test can state what is to happen before stating what the mock should # receive. module Test::Unit::MockTalk def because(&block) @because = block self end alias_method :during, :because alias_method :whenever, :because def behold! yield @because.call end end # Use this class when creating a mock that's to receive a notification. # I don't know why you can't use NSObject, but you can't -- the notification # will not be received. class SomeRandomWatcher < OSX::NSObject end # Use this in a _with_ expectation. def this_notification(name, object = nil, userInfo = nil) on { | notification | notification.name == name && notification.object == object && notification.userInfo == userInfo.to_ns } end class RawNotificationTests < Test::Unit::TestCase include Test::Unit::MockTalk def setup @observed = NSObject.alloc.init @watcher = flexmock(SomeRandomWatcher.alloc.init) end should "observe a name/object combination - both must be present" do center = NSNotificationCenter.defaultCenter center.addObserver_selector_name_object(@watcher, :posted, "name", @observed) during { center.postNotificationName_object_userInfo( "name", @observed, :key => :value) center.postNotificationName_object_userInfo( "name", :a_random_object, :key => :value) center.postNotificationName_object_userInfo( "WRONG_NAME", @observed, :key => :value) }.behold! { @watcher.should_receive(:posted). once.with(this_notification("name", @observed, :key => :value)) } end end