How can I replace the message body programmatically in Smalltalk?

As part of some testing, I am temporarily replacing the contents of the message with those that will return a predictable set of test values. What is the standard Smalltalk-y way to do this kind of work? Is there any sample code to view?

Some explanations:

  • No, this is not just a unit test. I am testing a large, complex system.
  • Replacing the entire object at runtime is impractical. A significant accumulated state would have to be curtailed by testing without replacing the method.
  • Subclass and replacement of one method are not generalized. I test dozens of similar classes and thousands of objects. Filling the class hierarchy with tiny one class of methods, one for each test case, will really suck - and this will require more updating if I change my test case.

Here is some pseudo code for what I want 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'.
+3
source share
4 answers

To replace one message with another, you can:

a) in the appropriate method (s), change the selector that is responsible for transmitting this message.

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

+4
source

MethodWrappers . , " ", Smalltalk, Pharo Squeak ( ). , . , :

MyClass methodDict at: #foo put: MyClassAsMethod new.

MyClassMethod #run: aSelector with: arguments in: aReceiver

, : MyClass new foo. VM , NOT CompiledMethod, , #run: with: in:

, pharo : https://gforge.inria.fr/frs/download.php/27524/Pharo-1.1.1-OneClickCogVM.zip

MethodWrappers .

+4
+3

My first thought was to subclass and override only the specific message that you want to return test values. However, you probably want to read the subclass for validation and the subclass for validating anti-patterns in the Wiki.

To make this temporary, you will need to replace the test object with an instance of the subclass, and then swap it back to the original class.

+2
source

Source: https://habr.com/ru/post/1786980/


All Articles