Skip to Content
Dec 11, 2019 at 11:55 AM

Trying to add ABAP unit tests to a global class but could do with some help


Hi Folks,

as some of you know I'm struggling with a lot of ABAP OO stuff and am therefore quite happy that I at least managed to create a global class in a sandbox system doing what it's supposed to do, namely performing some checks before DDIC-objects get added to a transport. Here is the outline of the class and its methods:

What I'd like to do now is to add a test class in order to unit test the various methods in the class. So, yes, I didn't create the code via TDD as that wouldn't have ended well due to my basic struggles with OO as it would have added way too much complexity due to things I still don't understand and find confusing. However, as the logic will be in a pretty central and critical location I do see the advantage to have unit tests to ensure that future changes do not break the code.

For some methods this should be fairly straightforward as they only need to verify the import parameters and return abap_false or abap_true dependend on their content. I think (hope?) that I can create those routines with the help of various documents found online (e.g. Joachim Rees's blog post, several posts by James E. McDonough and others) and in books (e.g. Paul Hardy's chapter 5 from ABAP to the Future ed. 3). The latter also explains why it's quite okay to introduce FRIENDS in order to allow unit tests for private methods, something I wholeheartedly agree with! I already tried to make sure that the methods get all the information they need via importing parameters instead of directly from fields like sy-uname, sy-sysid and others in SYST so that the unit tests can work with other values than these (or wouldn't that have been necessary at all?).

What I am struggling with is what to do about the two routines which read TADIR (GET_SRCSYSTEM_FROM_TADIR) and a Z-Table (ENTRY_EXISTS_ZBC_DDIC_CHECK). I know that I'll have to somehow "trick" the unit test to play with provided data instead of actually reading the table, but I'm stymied of how to properly tweak my code to make it so.

From reading Paul's chapter, I gather that as a first step, I should move these two methods into a global class of their own where they'll then be public instead of private. Where I get lost is with deciding of what I need to define/code where and why. So, what goes in the test class and how do I need to rewrite the production code to allow "mocking" (or whatever the correct term is)? The thing I think I'm most confused about is where interface definitions for the global class(es) come in to allow testing. Is this a "must have" or is it just a "nice to have" and if the former how & where do I need to do this?

Not sure which code-snippets are needed to answer these questions, so here are some as an example for the SELECT from TADIR:

private definitions:

    METHODS source_system_okay_for_ddic
        i_transport_objects            TYPE tr_objects
        i_sysid                        TYPE sy-sysid
        e_message                      TYPE bapiret2
        VALUE(r_correct_source_system) TYPE abap_bool.
    METHODS get_srcsystem_from_tadir
        i_transport_object  TYPE e071
        VALUE(r_srcsystem) TYPE tadir-srcsystem.

from main routine

"Now check that DDIC-system is source system of all objects in transport via TADIR
IF source_system_okay_for_ddic( EXPORTING i_transport_objects = i_transport_objects
                                          i_sysid             = i_sysid
                                IMPORTING e_message = message ).
  "All good and transport can be saved with objects
  "At least one object in transport has not been migrated to DDIC-system yet and message
  "information was filled in method accordingly
  APPEND message TO r_message.


  METHOD source_system_okay_for_ddic.
    " Method SOURCE_SYSTEM_OKAY_FOR_DDIC (private)
    "   IMPORTING i_transport_objects TYPE tr_objects
    "             i_sysid             TYPE sy-sysid
    "   EXPORTING e_message           TYPE bapiret2
    "   RETURNING VALUE(r_correct_source_system)  TYPE abap_bool
    "Default assumption is that system is okay for DDIC-maintenance
    r_correct_source_system = abap_true.
    CLEAR e_message.

    LOOP AT i_transport_objects INTO DATA(transport_object).
      DATA(lv_srcsystem) = get_srcsystem_from_tadir( transport_object ).

      IF lv_srcsystem NE space.


  METHOD get_srcsystem_from_tadir.
    " Method ENTRY_EXISTS_ZBC_DDIC_CHECK (private)
    "   IMPORTING i_transport_object        TYPE e071
    "   RETURNING VALUE(r_srcsystem)        TYPE tadir-srcsystem
    CLEAR r_srcsystem.
    SELECT SINGLE srcsystem
             INTO @r_srcsystem
             FROM tadir
            WHERE object   = @i_transport_object-object
              AND obj_name = @i_transport_object-obj_name(40).

Any takers to help with this? And please let me know if this is not the best place to ask.

Thanks & Cheers