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