lib/caricature/clr/isolator.rb in caricature-0.7.2 vs lib/caricature/clr/isolator.rb in caricature-0.7.5
- old
+ new
@@ -1,7 +1,109 @@
module Caricature
+ # Groups the methods for interception together
+ # this is a mix-in for the created isolations for classes
+ module Interception
+
+ # the class methods of this intercepting object
+ module ClassMethods
+
+ # Raises an event on the isolation
+ # You can specify the arguments in the block or as parameters
+ #
+ # Example
+ #
+ # an_isolation.class.raise_event :on_property_changed do |raiser|
+ # raiser.with an_isolation, System::EventArgs.empty
+ # end
+ #
+ # is equivalent to:
+ #
+ # an_isolation.class.raise_event :on_property_changed, an_isolation, System::EventArgs.empty
+ #
+ # or
+ #
+ # an_isolation.class.raise_event(:on_property_changed).with(an_isolation, System::EventArgs.empty)
+ #
+ # You will most likely use this method when you want to verify logic in an event handler
+ # You will most likely use this method when you want to verify logic in an event handler
+ def raise_event(event_name, *args, &block)
+ isolation_context.add_event_expectation event_name, :class, *args, &block
+ end
+
+ # Verifies whether the specified event was raised
+ #
+ # You will probably be using this method only when you're interested in whether an event has been raised
+ # during the course of the test you're running.
+ def did_raise_event?(event_name, &b)
+ isolation_context.verify_event_raise event_name, :class, &b
+ end
+
+ end
+
+ # Raises an event on the isolation
+ # You can specify the arguments in the block or as parameters
+ #
+ # Example
+ #
+ # an_isolation.raise_event :on_property_changed do |raiser|
+ # raiser.with an_isolation, System::EventArgs.empty
+ # end
+ #
+ # is equivalent to:
+ #
+ # an_isolation.raise_event :on_property_changed, an_isolation, System::EventArgs.empty
+ #
+ # or
+ #
+ # an_isolation.raise_event(:on_property_changed).with(an_isolation, System::EventArgs.empty)
+ #
+ # You will most likely use this method when you want to verify logic in an event handler
+ def raise_event(event_name, *args, &block)
+ isolation_context.add_event_expectation event_name, :instance, *args, &block
+ end
+
+ # Raises an event on the isolation
+ # You can specify the arguments in the block or as parameters
+ #
+ # Example
+ #
+ # an_isolation.raise_class_event :on_property_changed do |raiser|
+ # raiser.with an_isolation, System::EventArgs.empty
+ # end
+ #
+ # is equivalent to:
+ #
+ # an_isolation.raise_class_event :on_property_changed, an_isolation, System::EventArgs.empty
+ #
+ # or
+ #
+ # an_isolation.raise_class_event(:on_property_changed).with(an_isolation, System::EventArgs.empty)
+ #
+ # You will most likely use this method when you want to verify logic in an event handler
+ def raise_class_event(event_name, *args, &block)
+ self.class.raise_event event_name, *args, &block
+ end
+
+ # Verifies whether the specified event was raised
+ #
+ # You will probably be using this method only when you're interested in whether an event has been raised
+ # during the course of the test you're running.
+ def did_raise_event?(event_name, &b)
+ isolation_context.verify_event_raise event_name, :instance, &b
+ end
+
+ # Verifies whether the specified event was raised
+ #
+ # You will probably be using this method only when you're interested in whether an event has been raised
+ # during the course of the test you're running.
+ def did_raise_class_event?(event_name, &b)
+ self.class.did_raise_event? event_name, &b
+ end
+
+ end
+
# A proxy to CLR objects that records method calls.
# this implements all the public instance methods of the class when you use it in ruby code
# When you use it in a CLR class you're bound to CLR rules and it only overrides the methods
# that are marked as virtual. We also can't isolate static or sealed types at the moment.
class ClrIsolator < Isolator
@@ -26,28 +128,30 @@
def initialize_messenger
@context.messenger = ClrClassMessenger.new @context.expectations, @subject
end
# builds the Isolator class for the specified subject
- def create_isolation_for(subj)
+ def create_isolation_for(subj)
members = @descriptor.instance_members
class_members = @descriptor.class_members
+ events = @descriptor.events
+ class_events = @descriptor.class_events
klass = Object.const_set(class_name(subj), Class.new(subj))
klass.class_eval do
include Interception
# access to the proxied subject
def ___super___
isolation_context.instance
- end
-
- def initialize(*args)
- self
end
+ def initialize(*args)
+ self
+ end
+
members.each do |mem|
nm = mem.name.to_s.to_sym
define_method nm do |*args|
b = nil
b = Proc.new { yield } if block_given?
@@ -61,11 +165,28 @@
b = nil
b = Proc.new { yield } if block_given?
isolation_context.send_class_message(mn, nil, *args, &b)
end
end
+
+ evts = (events + class_events).collect do |evt|
+ %w(add remove).inject("") do |res, nm|
+ res << <<-end_event_definition
+
+def #{"self." unless evt.instance_member?}#{nm}_#{evt.event_name}(block)
+ self.isolation_context.#{nm}_event_subscription('#{evt.event_name}', :#{evt.instance_member? ? "instance" : "class"}, block)
+end
+
+ end_event_definition
+ end
+ end.join("\n")
+
+ klass.class_eval evts
+
+ #puts evts
+
end
klass
end
@@ -90,10 +211,11 @@
end
# builds the actual +isolator+ for the CLR interface
def create_isolation_for(subj)
proxy_members = @descriptor.instance_members
+ events = @descriptor.events
klass = Object.const_set(class_name(subj), Class.new)
klass.class_eval do
include subj
@@ -106,10 +228,24 @@
b = Proc.new { yield } if block_given?
isolation_context.send_message(nm, mem.return_type, *args, &b)
end
end
+
end
+
+ evts = events.collect do |evt|
+ %w(add remove).inject("") do |res, nm|
+ res << <<-end_event_definition
+
+def #{"self." unless evt.instance_member?}#{nm}_#{evt.event_name}(block)
+ isolation_context.#{nm}_event_subscription('#{evt.event_name}', :#{evt.instance_member? ? "instance" : "class"}, block)
+end
+
+ end_event_definition
+ end
+ end.join("\n")
+ klass.class_eval evts
klass
end
end
\ No newline at end of file