Home

On-the-fly Mock classes

Some time ago, I implemented a neat hack in SUnit that I had a use for again today. I thought I might share it here.

The issue is that you often want to have a subclass of a tested class that overrides one or two methods with very specific (to that test) behavior. Say you have a user class, and somewhere in your code the messsage #save is sent. During your test, you just want to know whether the message is sent. This hack allows you to do so right in the test code.

Without further ado, the methods in TestCase I added:

TestCase>>makeMockSubclassOf: class
    instanceVariables: ivars
    methods: methods
    classMethods: classMethods

| answer |
answer := ClassBuilder new
	newSubclassOf: class
	type: #normal
	instanceVariables: ivars
	from: nil.
methods do: [:each |
	answer compileSilently: each classified: nil].
classMethods do: [:each |
	answer class compileSilently: each classified: nil].
^answer

TestCase>>withMockSubclassOf: class
    instanceVariables: ivars
    methods: methods
    classMethods: classMethods
    do: aBlock

| mock |
mock := self makeMockSubclassOf: class
            instanceVariables: ivars
            methods: methods
            classMethods: classMethods.
[aBlock value: mock]
	ensure: [class removeSubclass: mock]

The second method is the one you’ll use. For example:

MyTestCase>>testUserSave

self withMockSubclassOf: User
	instanceVariables: 'isSaved'
	methods: #(
		'isSaved ^isSaved'
		'save isSaved := true')
	classMethods: #()
	do:  [:mock  |
                   | user |
                   user := mock new.
                   user doSomethingThatWillCallSave.
                   self assert: user isSaved]

At the end of the test, the mock class will be removed.

The advantage to this method over the “classical” method of creating stand-alone mock subclasses, is that you can really tailor the behavior to your test (mock classes tend to grow to accumulate a number of tests), and that the mock behaviour is “right there”.


Stumble it!  Post to del.icio.us 

One Response to “On-the-fly Mock classes”

  1. Wilkes Joiner Says:

    I end up do a fair bit of this with anonymous inner classes in Java and was wonder how do this in Smalltalk.

    Thanks!
    Wilkes

Leave a Reply

(note: comments may be moderated so don't always appear right away)


Copyright (C)2000-2005 Cees de Groot -- All rights reserved.