EDUCAÇÃO E TECNOLOGIA

SAP ABAP Unit Test – How to deal with classes of static methods

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.