Orangutan is a library for creating stubs.

It allows you to create stub objects and to specify methods to return and yield values as well as to raise errors.

It can be used in testing .net code using ironruby although at this stage only the simplest of clr interfaces can be stubbed.

Note that only stub instances of objects are created. It can not create mocks of class methods.

It works by recording all method calls so that assertions can be made about them after the fact and providing a simple dsl for setting up stubbed methods (which can be used as expectations to assert on later).

Orangutan can be used with any testing framework and in combination with other mock frameworks.

Installation:

gem install orangutan

Some examples of usage (note that these are not in the context of any testing framework and are intended only to indicate how to use the api):

require ‘orangutan’

include Orangutan::Chantek

reset_stubs

# Creating a pure ruby stub @stub = stub :stub

# Creating a stub that implements a clr interface @clr_stub = stub :clr_stub, :clr_interface => System::IDisposable

# Setting up stub methods that return values so_when(:stub).receives(:execute).with(7).return(‘baz’)

# Setting up stub methods that yield values so_when(:stub).receives(:execute).with(7).yield(‘baz’)

# Setting up stub methods that raise errors so_when(:stub).receives(:execute).with(7).raise(‘baz’)

# checking whether an expectation was met expectation = so_when(:stub).receives(:execute).with(7) puts expectation.matched? (=> false) @stub.execute(7) puts expectation.matched? (=> false)

# setting limits on expectations

so_when(:stub).receives(:execute).with(7).once so_when(:stub).receives(:execute).with(7).twice so_when(:stub).receives(:execute).with(7).exactly(4).times

# Note that once an expectation has reached its limit, it will no longer match. # Expections will match in the order they are specified. # This mechanism can be used to set up more complex expected call sequences:

e1 = so_when(:stub).receives(:execute).with(7).return(‘ok’).once e2 = so_when(:stub).receives(:execute).return(‘hmm’).twice

puts e1.count (=> nil) puts e2.count (=> nil) @stub.execute(7) (=> ‘ok’) puts e1.count (=> 1) puts e2.count (=> nil) @stub.execute(7) (=> ‘hmm’) puts e1.count (=> 1) puts e2.count (=> 1) @stub.execute(7) (=> ‘hmm’) puts e1.count (=> 1) puts e2.count (=> 2) @stub.execute(7) (=> nil) puts e1.count (=> 1) puts e2.count (=> 2) puts e1.matched? (=> true) puts e2.matched? (=> true)

# Checking all expectations expectations.any? {|e| !e.matched? }

# Examining recorded method calls calls.each {|call| puts “#{call.name}.#callcall.method(#callcall.argscall.args.join(‘,’))” }

# Recorded call sequences can also be used for assertions in combination with or instead of checking expectations.

Questions:

  • Why Orangutan?

My daughter likes orangutans and I couldn’t think of a better name. Both Sumatran and Bornean orangutans are endangered species so even if you intensely dislike this project or its implementation, at least you can be made aware of the plight of these spectacular creatures.

  • Did it have anything to do with Clyde in “Every Which Way But Loose”

Definately not. What a ridiculous question. I’m appalled.

  • What’s Chantek?

Chantek is a famous orangutan that can solve sudokus and the rubik’s cube - en.wikipedia.org/wiki/Chantek

  • Why do I not need to register this as a mock framework?

Most frameworks such as rspec’s mocks, mocha and stubba replace methods on existing classes. Because this can’t be done with this library - you can only create pure stub objects and setup method behaviours, there’s nothing that needs to be undone at the end of a test/example.