Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

How to extend methods on fly (See related posts)

Here is how i extend object methods on fly. It is very useful when doing testing and mocks, because my testing framework can create mocks for simple things like counting calls to some methods automatically without me defining all the mocks.

For you on buzzwords, you can DRY up your tests and get rid of some repeating mocks using this technique.

module Magic
  class Mock
    def self.method instance, method_name, &new_method
      mock_alias = Class.new
      (instance.methods).each do |method|
        mock_alias.send(:define_method, method) do |*args|
          instance.send(method, *args)
        end
      end
      mock = Class.new(mock_alias) do
        define_method(method_name, &new_method)
      end
      mock.new
    end
  end
end

# usage
hello = "hello"
mock = Magic::Mock.method(hello , :to_s) do
  super + " from mock"
end
puts mock.to_s # hello from mock
puts hello.to_s # hello


So for an example use in tests:

def assert_called object, method, message = nil
  calls = 0
  mock = Magic::Mock.method(object, method) do
    calls += 1
    super
  end
  yield(mock)
  message ||= "Method #{method} was not called during block but was expected to."
  assert_equal calls, 1, message
end


Then i can do in my tests:

def test_greet_calls_bark
  assert_called (Dog.new, :bark) { |dog|
    dog.greet
  }
end


Instead of creating mock classes (more code), thus introducing fewer bugs to my tests:)


You need to create an account or log in to post comments to this site.


Click here to browse all 7305 code snippets

Related Posts