Search code examples
metaprogrammingsmalltalk

How do I replace a message body programmatically in Smalltalk?


As part of some testing, I'm looking to, temporarily, replace the contents of a message with one that will return a predictable set of test values. What is the standard Smalltalk-y way to do this type of work? Is there some sample code for me to look at?

Some clarification:

  • No, this is not a simple unit test. I'm testing a large, complex, system.
  • Replacing the whole object at runtime is impractical. Significant accumulated state would have to be twiddled by the test, beyond replacing the method.
  • Subclassing and replacing one method doesn't generalize. I'm testing dozens of similar classes and thousands of objects. Filling up the class hierarchy with tiny one method classes, one for each test-case, would really suck - and it would suck even more to have to update them if I change my test case.

Here's some pseudocode for what I'm looking to write:

replaceMessage: 'fibonacci' 
       onClass: 'funFunctions' 
          with: 'returnsPredictableNumbersWithoutCalculatingThem'.

self runTestSet1.

restoreMessage: 'fibonacci' 
       onClass: 'funFunctions'.

self runFollowUpSet1. "Depends on state set by Set1"

replaceMessage: 'fibonacci' 
       onClass: 'funFunctions' 
          with: 'returnsPredictableNumbersWithoutCalculatingThemPart2'.

self runFollowUpSet2. "Depends on state set by followupset1"

restoreMessage: 'fibonacci' 
       onClass: 'funFunctions'.

Solution

  • To replace one message with another you could:

    a) in corresponding method(s), change the selector, which responsible for given message send.

    b) use proxies, to wrap all objects of interest and intercept given message in order to use different evaluation path than in original method.