require 'osx/cocoa' include OSX require 'flexmock/test_unit' class Observed < OSX::NSObject kvc_accessor :value def init @value = 0 super_init end # The need for this is, I think, a bug in RubyCocoa. def self.automaticallyNotifiesObserversForKey(key) false end end class Watcher < OSX::NSObject def observeValueForKeyPath_ofObject_change_context( keyPath, object, change, context) end end class KVOTests < Test::Unit::TestCase def setup super @observed = Observed.alloc.init @watcher = flexmock(Watcher.alloc.init) @observed.addObserver_forKeyPath_options_context( @watcher, 'value', OSX::NSKeyValueObservingOptionNew | OSX::NSKeyValueObservingOptionOld, nil) end def teardown @observed.removeObserver_forKeyPath(@watcher, 'value') super end def this_change(expected) @watcher.should_receive(:observeValueForKeyPath_ofObject_change_context). once. with('value', @observed, on { | actuals | actuals[:old] == expected[:old] && actuals[:new] == expected[:new] }, nil) end def test_setting_in_ruby_style newval = 5 during { @observed.value = newval }.behold! { this_change(:old => @observed.value, :new => newval) } assert_equal(newval, @observed.value) end def because(&block) @because = block self end alias_method :during, :because def behold! yield @because.call end end