One way is this https://blogs.sap.com/2021/08/23/sap-abap-unit-test-for-static-dependency-class-with-a-hack/ from Ravirajsinh Gohil
But this is the way I do it.
Let’s say, in the mists of time, someone created a static method in a class. Now, we all know now that is a bad idea, but back then, we were young, naive and full of dreams. I remember some of my dreams. The one with the carnivorous trombones was particularly traumatic.
The class has one method:
CLASS zcl_utility DEFINITION. PUBLIC SECTION. CLASS-METHODS: is_client_open RETURNING VALUE(r_result) TYPE abap_bool. ENDCLASS. CLASS zcl_utility IMPLEMENTATION. METHOD is_client_open. IF ... r_result = abap_true. ENDIF. ENDMETHOD. ENDCLASS.
It’s naturally called by:
METHOD wot_does_something. IF zcl_utility=>is_client_open( ). ... ENDMETHOD.
But we really want to test double this, so that we can put our code in a test harness.
First create a local interface and class.
CLASS lif_utility DEFINITION. METHODS: is_client_open RETURNING VALUE(r_result) TYPE abap_bool. ENDCLASS. CLASS lcl_utility IMPLEMENTATION. METHOD is_client_open. r_result = zcl_utility=>is_client_open( ). ENDMETHOD. ENDCLASS.
In my main class I have:
...DEFINITION. CLASS-DATA _utility TYPE REF TO lif_utility. CLASS-METHODS class_constructor. ...IMPLEMENTATION. METHOD class_constructor. _utility = NEW lcl_utility( ). ENDMETHOD. METHOD wot_does_something. IF _utility->is_client_open( ). ... ENDMETHOD.
Now the static method call is an instance method call. And it’s a class implementing an interface, which means now we can implement a test double.
CLASS ltd_utility DEFINITION FOR TESTING. PUBLIC SECTION. INTERFACES lif_utility. ENDCLASS. ... CLASS ltc_my_test DEFINITION FOR TESTING DURATION short ... PRIVATE SECTION. DATA: utility TYPE REF TO ltd_utility, cut TYPE REF TO zmy_main_class. METHODS: setup. ... ENDCLASS. CLASS ltc_my_test IMPLEMENTATION. METHOD setup. cut = new #( ). utility = new #( ). cut->_utility = utility. ENDMETHOD. ENDCLASS.
_utility is private, but this resolved by making ltc_my_test a local friend of the main class.
Now, when the test methods run, instead of the lcl_utility methods being called, the ltd_utility methods will be called.
I prefer this method of injection to constructor injection. But of course, this approach will work for that as well.