# \[ANN\] Test::Unit::Mock: Mock objects for testing with Test::Unit

**URL:** <https://rubytalk.org/t/ann-test-unit-mock-mock-objects-for-testing-with-test-unit/5009>\
**Category:** ruby-talk\
**Created:** [5 March 2003 01:13 UTC](https://rubytalk.org/t/ann-test-unit-mock-mock-objects-for-testing-with-test-unit/5009 "2003-03-05T01:13:11Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Michael\_Granger](https://avatars.discourse-cdn.com/v4/letter/m/a88e4f/32.png) [@Michael\_Granger](https://rubytalk.org/u/Michael_Granger)\
**Post date:** [5 March 2003 01:13 UTC](https://rubytalk.org/t/ann-test-unit-mock-mock-objects-for-testing-with-test-unit/5009/1 "2003-03-05T01:13:11Z")

</div>

Hi fellow Rubyists,

I’d like to announce the initial release of Test::Unit::Mock, a mock  
object class for Test::Unit test suites.

Test-Unit-Mock is a class for conveniently building mock objects in  
Test::Unit test cases. It is based on ideas in Ruby/Mock by Nat Pryce,  
but is a bit (IMHO) easier to use, and more flexible.

It allows you do make a mocked object that will respond to all the  
methods of the real class (albeit probably not with correct results)  
with one line of code. Eg.,

mockSocket = Test::Unit::MockObject( TCPSocket ).new

You can then specify return values for the methods you wish to test in  
one of several different ways:

# Make the #addr method return three cycling values (which will be

# repeated when it reaches the end

mockSocket.setReturnValues( :addr =\> [  
[“AF\_INET”, 23, “localhost”, “127.0.0.1”],  
[“AF\_INET”, 80, “[slashdot.org](http://slashdot.org)”, “66.35.250.150”],  
[“AF\_INET”, 2401, “[helium.ruby-lang.org](http://helium.ruby-lang.org)”, “210.251.121.214”],  
] )

# Make the #write and #read methods call a Proc and a Method,

# respectively

mockSocket.setReturnValues( :write =\> Proc::new {|str| str.length},  
:read =\> method(:fakeRead) )

# Set up the #getsockopt method to return a value based on the

# arguments given:

mockSocket.setReturnValues( :getsockopt =\> {  
[Socket::SOL\_TCP, Socket::TCP\_NODELAY] =\> [0].pack(“i\_”),  
[Socket::SOL\_SOCKET, Socket::SO\_REUSEADDR] =\> [1].pack(“i\_”),  
} )

You can also set the order in which you expect methods to be called, but  
you don’t have to do so if you don’t care:

mockSocket.setCallOrder( :addr, :getsockopt, :write, :read, :write )

By default, when testing for call order, other method calls may be  
interspersed between the calls specified without effect, and only a  
missing or misordered method call causes the assertions to fail. If you  
want the call order to be adhered to strictly, you can set that:

mockSocket.strictCallOrder = true

Then, when you’re ready to test, just activate the object and send it  
off to whatever code you’re testing:

mockSocket.activate  
testedObject.setSocket( mockSocket )  
…

# Check method call order on the mocked socket (adds assertions)

mockSocket.verify

Assertion failures contain a message that specifies exactly what went  
wrong, eg.:

$ ruby misc/readmecode.rb

```
1) Failure!!!

```

test\_incorrectorder(MockTestExperiment) [./mock.rb:255]:  
Call order assertion failed: Expected call to :write, but got  
call to :read from misc/readmecode.rb:77:in `test\_incorrectorder’  
at 0.00045 instead

```
2) Failure!!!

```

test\_missingcall(MockTestExperiment) [./mock.rb:255]:  
Call order assertion failed: Missing call to :read.

If you require more advanced functionality, you can also use the mocked  
object class as a superclass:

# Create a mock socket class

class MockSocket \< Test::Unit::MockObject( TCPSocket )  
def initialize  
super  
setCallOrder( :read, :read, :read, :write, :read )  
strictCallOrder = true  
@io = ''  
end

```
   def read( len )
       super # Call the mocked method to record the call
       rval = @io[0,len]
       @io[0,len] = ''

       return rval
   end

   def write( str )
       super # Call the mocked method to record the call
       @io += str
       return str.length
   end

```

end

You can also add debugging to your tests to give you a timestamped  
history of each call to the mock object:

# Call the methods in the correct order

mockSocket.addr  
mockSocket.getsockopt( Socket::SOL\_TCP, Socket::TCP\_NODELAY )  
mockSocket.write( “foo” )  
mockSocket.read( 1024 )  
mockSocket.write( “bar” )  
mockSocket.read( 4096 )

# Check method call order on the mocked socket

mockSocket.verify

if $DEBUG  
puts “Call trace:\n\t” + mockSocket.callTrace.join("\n\t")  
end

This outputs something like:

Call trace:  
addr( ) at 0.00015 seconds from readmecode.rb:64:in `test' getsockopt( 6,1 ) at 0.00030 seconds from readmecode.rb:65:in`test’  
write( “foo” ) at 0.00040 seconds from readmecode.rb:66:in `test' read( 1024 ) at 0.00050 seconds from readmecode.rb:67:in`test’  
write( “bar” ) at 0.00063 seconds from readmecode.rb:68:in `test' read( 4096 ) at 0.00072 seconds from readmecode.rb:69:in`test’

You can read the documentation or download it from the project page at:

[http://www.deveiate.org/code/Test-Unit-Mock.shtml](http://www.deveiate.org/code/Test-Unit-Mock.shtml)

I hope it’s useful. Thanks to Nathaniel Talbott for all his work on  
Test::Unit, and to Nat Pryce for his on Ruby/Mock.

> **···**
>
> –  
> Michael Granger [ged@FaerieMUD.org](mailto:ged@FaerieMUD.org)  
> Rubymage, Believer, Architect  
> The FaerieMUD Consortium [http://www.FaerieMUD.org/](http://www.FaerieMUD.org/)

---

<div class="post-metadata">

**Author:** ![Jim\_Weirich2](https://avatars.discourse-cdn.com/v4/letter/j/ecc23a/32.png) [@Jim\_Weirich2](https://rubytalk.org/u/Jim_Weirich2)\
**Post date:** [5 March 2003 12:27 UTC](https://rubytalk.org/t/ann-test-unit-mock-mock-objects-for-testing-with-test-unit/5009/2 "2003-03-05T12:27:51Z")

</div>

Excellent! I was actually thinking about such changes to Mock object  
myself. I’m glad to find out someone else has already done the work.  
🙂

> **···**
>
> On Tue, 2003-03-04 at 20:13, Michael Granger wrote:
> 
> > Hi fellow Rubyists,
> > 
> > I’d like to announce the initial release of Test::Unit::Mock, a mock  
> > object class for Test::Unit test suites.
> > 
> > Test-Unit-Mock is a class for conveniently building mock objects in  
> > Test::Unit test cases. It is based on ideas in Ruby/Mock by Nat Pryce,  
> > but is a bit (IMHO) easier to use, and more flexible.
> 
> ## – – Jim Weirich [jweirich@one.net](mailto:jweirich@one.net)[http://w3.one.net/~jweirich](http://w3.one.net/~jweirich)
> 
> “Beware of bugs in the above code; I have only proved it correct,  
> not tried it.” – Donald Knuth (in a memo to Peter van Emde Boas)
