RR is a Ruby library that lets you create and work with test doubles. Test doubles are useful because they let you temporarily replace parts of your code during a test, similar to how a producer might use a stunt double to temporarily take the place of an actor in a movie. You can use a test double to override a method on an object with a simpler implementation; create an object that responds to a particular method; or even establish an expectation that a particular method should be called on a object, which will be verified after your test runs.
RR features a succinct syntax which aims to makes it easier to translate main code to test double form by matching double definitions on methods as closely as possible to actual invocations of those methods. In addition, RR differs from existing mock / test double frameworks by staying out of the global Object class; instead, it limits its scope to your surrounding test case, and asks that beyond this scope you explicitly wrap any objects on which you want to define test doubles.
Finally, RR provides adapters so you can integrate it with your test framework of choice, whether RSpec, Test::Unit or MiniTest/MiniSpec. RR is tested against all active Ruby versions.
RR was created by Brian Takita. Previously maintained by Elliot Winkler and currently by Kouhei Sutou.
RR includes a rich set of test double strategies. Following is a sample of what RR looks like.
# Stub a method to return nothing
stub(object).foo
stub(MyClass).foo { 'bar' }
# Stub a method to always return a value
stub(object).foo { 'bar' }
stub(MyClass).foo { 'bar' }
# Stub a method to return a value when called with certain arguments
stub(object).foo(1, 2) { 'bar' }
stub(MyClass).foo(1, 2) { 'bar' }
# Create an expectation on a method
mock(object).foo
mock(MyClass).foo
# Create an expectation on a method
# and stub it to always return a value
mock(object).foo { 'bar' }
mock(MyClass).foo { 'bar' }
# Create an expectation on a method with certain arguments
# and stub it to return a value when called that way
mock(object).foo(1, 2) { 'bar' }
mock(MyClass).foo(1, 2) { 'bar' }
# Intercept a existing method without completely overriding it,
# and create a new return value from the existing one
stub.proxy(object).foo {|str| str.upcase }
stub.proxy(MyClass).foo {|str| str.upcase }
# Do the same thing except also create an expectation
mock.proxy(object).foo {|str| str.upcase }
mock.proxy(MyClass).foo {|str| str.upcase }
# Intercept a class's new method and define a double on the return value
stub.proxy(MyClass).new {|obj| stub(obj).foo; obj }
# Do the same thing except also create an expectation on .new
mock.proxy(MyClass).new {|obj| stub(obj).foo; obj }
# Stub a method on an instance of MyClass when it is created
any_instance_of(MyClass) do |klass|
stub(klass).foo { 'bar' }
end
# Another way to do this which gives you access to the instance itself
stub.proxy(MyClass).new do |obj|
stub(obj).foo { 'bar' }
end