Dependency injection to class-method in ABAP

jcjr

I have a scenario where my class method (A) calls another class method (B). So A is depended on B. I’d like to get rid of the dependency to be able to run unit tests. Decoupling and dependency injection are somewhat based on instantiation. But class methods (static methods) don’t need an instance by nature. I’ve already made two solutions working, but none of them seems 100% for me:

  1. We create instance of class B (production code) or instance of the test double (for unit test). We inject it as a parameter to the class method under test. The inner class method is called on the injected instance, not on the class.

I don’t like we need to make an instance of class, although we are using class method. It can take time. It needs a bit more code.

  1. We inject actual class name as a string parameter and we use dynamic CALL METHOD.

As I am not fan of interpreted languages, I consider this a mess that can bring serious runtime problems. Since we do this to implement unit tests and consequently to eliminate possible bugs; using dynamic calls seems counterproductive. Also it is painful to work with parameters.

Is there another way to solve this? Is there some important point I missed?

Bellow, there are key parts of both solutions. There are not essential to understand the problem, but they might help.

1)

INTERFACE lif_readfile.
  CLASS-METHODS gui_upload
    IMPORTING file_path TYPE string
    CHANGING data_tab  TYPE truxs_t_text_data.
ENDINTERFACE.

CLASS lcl_file_operations DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS:
      get_file_length
        IMPORTING
          !file_path         TYPE string
        CHANGING
          !filereader        TYPE REF TO lif_readfile OPTIONAL
        RETURNING
          VALUE(text_length) TYPE i.
ENDCLASS.

CLASS lcl_file_operations IMPLEMENTATION.
  METHOD get_file_length.

*create instance of default productive class
    IF filereader IS NOT BOUND.
      filereader = NEW lcl_readfile( ).
    ENDIF.

*use instance to call class method
    filereader->gui_upload(
      EXPORTING file_path = file_path
        CHANGING data_tab = lt_data
    ).

*code under test here..

  ENDMETHOD.
ENDCLASS.

2)

CLASS lcl_file_operations DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS:
      get_file_length
        IMPORTING
          !file_path         TYPE string
          !classname         TYPE string DEFAULT 'LCL_READFILE'
        RETURNING
          VALUE(text_length) TYPE i.
ENDCLASS.

CLASS lcl_file_operations IMPLEMENTATION.
  METHOD get_file_length.

*parameter definition
    ptab = VALUE #( ( name  = 'FILE_PATH'
                      kind  = cl_abap_objectdescr=>exporting
                      value = REF #( file_path ) )
                    ( name  = 'DATA_TAB'
                      kind  = cl_abap_objectdescr=>changing
                      value = REF #( lt_data ) ) ).

    DATA(meth)     = 'LIF_READFILE~GUI_UPLOAD'.

*dynamic call
    CALL METHOD (classname)=>(meth) PARAMETER-TABLE ptab.

*code under test here..

  ENDMETHOD.
ENDCLASS.
jcjr

I’ve found so far two solutions that appears better to me. But if you know even a better solution; I am still looking forward to try it.

Factory+injector (dependency lookup)

Improved solution 1 – handling of instances is moved to the factory. Code for the factory and injector is not provided – it is standard solution.

CLASS lcl_file_operations DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS:
      get_file_length
        IMPORTING
          !file_path         TYPE string
        RETURNING
          VALUE(text_length) TYPE i.
ENDCLASS.


CLASS lcl_file_operations IMPLEMENTATION.
  METHOD get_file_length.

    myfactory=>get_filereader( )->gui_upload(
      EXPORTING file_path = file_path
        CHANGING data_tab = lt_data
    ).

*code under test here..

  ENDMETHOD.
ENDCLASS.

Pros

  • Cleaner and shorter code under test. Instance is created and tested somewhere else.

Cons

  • It still creates instances.
  • More code in total.

Using TEST-SEAM and TEST-INJECTION

CLASS zcl_file_operations IMPLEMENTATION.
  METHOD get_file_length.

   TEST-SEAM seam_gui_upload.
     zcl_filereader=>gui_upload(
        EXPORTING file_path = file_path
        CHANGING data_tab = lt_data
     ).
   END-TEST-SEAM.

*code under test here..

  ENDMETHOD.
ENDCLASS.

FOR TESTING method

*...
TEST-INJECTION seam_gui_upload.
 ztc_testdouble=>gui_upload(
    EXPORTING file_path = file_path
    CHANGING data_tab = lt_data
 ).
END-TEST-INJECTION.
*...

Pros

  • This seems like the best solution so far.
  • Using class-methods; no instances created.
  • Shortest code in total.

Cons

  • Considered dirty technique by community (recommended only for legacy code).
  • Slight pollution of code under test.

Note

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Static class to dependency injection

From Dev

Dependency injection of context class in constructor

From Dev

Dependency Injection in HtmlHelper extension method?

From Dev

Swift dependency injection by passing class as a function parameter to call a class method

From Dev

Dependency injection IOption class library

From Dev

How to run non static method from static inside single class and use dependency injection C#

From Dev

Register Dependency Injection for generic class

From Dev

Use dependency injection in static class

From Dev

Dependency injection has no value for non-static class and static method in c#

From Dev

Dependency Injection in Angular/ Calling a method that belongs to a service from a class

From Dev

Dependency injection with a .Net Class Library?

From Dev

Using dependency injection how can I access a method in a class inside a service?

From Dev

Spring dependency injection and generic class

From Dev

Mock method on the same class with dependency Injection - PHP

From Dev

Dependency injection if a class needs to create multiple instances of another class when required in a method

From Dev

Method injection with optional class?

From Dev

How to convert this static class method into a dependency injection? (Specific code included)

From Dev

How to use Dependency Injection in class?

From Dev

Laravel dependency injection with base class

From Dev

Dependency Injection in child class

From Dev

.net core method dependency injection

From Dev

Dynamic dependency injection of a generic class

From Dev

call c# class method by reflection with constructor using dependency injection

From Dev

Dependency injection from one class to method of another class

From Dev

How to mock a static method of util class of a package using spring dependency injection

From Dev

Implementing an Interface on a class with Dependency Injection

From Dev

How to add Definiton of Symfony Dependency injection container builder from Class factory method?

From Dev

Count calls to method with Dependency Injection

From Dev

Constructor Injection (Dependency Injection) in a class (NOT Controller Class) in .net core

Related Related

  1. 1

    Static class to dependency injection

  2. 2

    Dependency injection of context class in constructor

  3. 3

    Dependency Injection in HtmlHelper extension method?

  4. 4

    Swift dependency injection by passing class as a function parameter to call a class method

  5. 5

    Dependency injection IOption class library

  6. 6

    How to run non static method from static inside single class and use dependency injection C#

  7. 7

    Register Dependency Injection for generic class

  8. 8

    Use dependency injection in static class

  9. 9

    Dependency injection has no value for non-static class and static method in c#

  10. 10

    Dependency Injection in Angular/ Calling a method that belongs to a service from a class

  11. 11

    Dependency injection with a .Net Class Library?

  12. 12

    Using dependency injection how can I access a method in a class inside a service?

  13. 13

    Spring dependency injection and generic class

  14. 14

    Mock method on the same class with dependency Injection - PHP

  15. 15

    Dependency injection if a class needs to create multiple instances of another class when required in a method

  16. 16

    Method injection with optional class?

  17. 17

    How to convert this static class method into a dependency injection? (Specific code included)

  18. 18

    How to use Dependency Injection in class?

  19. 19

    Laravel dependency injection with base class

  20. 20

    Dependency Injection in child class

  21. 21

    .net core method dependency injection

  22. 22

    Dynamic dependency injection of a generic class

  23. 23

    call c# class method by reflection with constructor using dependency injection

  24. 24

    Dependency injection from one class to method of another class

  25. 25

    How to mock a static method of util class of a package using spring dependency injection

  26. 26

    Implementing an Interface on a class with Dependency Injection

  27. 27

    How to add Definiton of Symfony Dependency injection container builder from Class factory method?

  28. 28

    Count calls to method with Dependency Injection

  29. 29

    Constructor Injection (Dependency Injection) in a class (NOT Controller Class) in .net core

HotTag

Archive