This is a test message to test the length of the message box.
Login
|
ABAP OO Injector
Created by Software-Heroes

ABAP OO - Injector

805

In the last article, we looked at ABAP OO and the evolution of design patterns, and how we can best use them. Therefore, in this article, we will delve deeper into the details of the injector for testability.

Advertising


In this article, we'll look at how the injector works and how you can use it together with the Factory to enable easy testability.

 

Introduction

In the last blog post in this series, we took a detailed look at the Factory and the Singleton. There, we examined the different stages of evolution and how we can further develop the pattern. You should read that article as a foundation before continuing with this one. We now want to use the factory and prepare it for our unit tests without having to change the actual code in the implementation.

 

Challenge

Currently, we have a global class in the system that is supposed to validate a timestamp. The class creates an instance of our implementation via the factory and passes it to the method. There, we check against a specific timestamp in the future. If you look at the code, however, we would have to wait until the unit test works once.

CLASS zcl_bs_demo_oo_test DEFINITION
  PUBLIC FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    METHODS validate_timestamp
      RETURNING VALUE(result) TYPE abap_boolean.
ENDCLASS.


CLASS zcl_bs_demo_oo_test IMPLEMENTATION.
  METHOD validate_timestamp.
    DATA(timestamp) = zcl_bs_demo_oo_factory=>create( ).
    RETURN xsdbool( timestamp->get_timestamp( ) = '20991231063000.0000000' ).
  ENDMETHOD.
ENDCLASS.

 

Currently, we have our component with a unit test. At runtime, the unit test calls the method, which then receives an instance back via the factory. However, our unit test won't work for many years, and then only for a very small fraction of the functionality. Therefore, the component isn't very testable at the moment.

 

Enhancement

To this end, we extend the scenario of the factory and the existing objects by adding another dimension. In this chapter, we will look at the various components and extend them.

 

Basics

From the last article, we need the following objects, although for our case we will only modify the Factory:

  • ZCL_BS_DEMO_OO_FACTORY
  • ZCL_BS_DEMO_OO_PRIVATE
  • ZIF_BS_DEMO_OO_INTERFACE

 

Injector

We now need to make two modifications simultaneously. To do this, we first create the new injector ZCL_BS_DEMO_OO_INJECTOR as a global class.

CLASS zcl_bs_demo_oo_injector DEFINITION
  PUBLIC ABSTRACT FINAL
  CREATE PUBLIC
  FOR TESTING.

  PUBLIC SECTION.
    CLASS-METHODS inject_double
      IMPORTING double TYPE REF TO zif_bs_demo_oo_interface OPTIONAL.
ENDCLASS.


CLASS zcl_bs_demo_oo_injector IMPLEMENTATION.
  METHOD inject_double.
    zcl_bs_demo_oo_factory=>double = double.
  ENDMETHOD.
ENDCLASS.

 

The injector has several properties that are important for its use:

  • ABSTRACT - The class should not be instantiable, but should only function via the provided methods and attributes.
  • FOR TESTING - The class should only be usable in the case of a unit test. Generally, the code is not compiled in test and production systems, but this serves as an additional safety net.
  • OPTIONAL - The double is static and should also be removable for further unit tests. Therefore, we set the parameter to Optional.

 

Factory

In the next step, we will adapt our factory. As a first step, we define the injector as a GLOBAL FRIEND so that it can also access protected methods and attributes. Secondly, we define a static attribute that contains the DOUBLE at runtime, and as a final step, we ensure that the CREATE method returns the Double when it has been set.

CLASS zcl_bs_demo_oo_factory DEFINITION
  PUBLIC ABSTRACT FINAL
  GLOBAL FRIENDS zcl_bs_demo_oo_injector.

  PUBLIC SECTION.
    CLASS-METHODS create
      RETURNING VALUE(result) TYPE REF TO zif_bs_demo_oo_interface.

  PRIVATE SECTION.
    CLASS-DATA double TYPE REF TO zif_bs_demo_oo_interface.
ENDCLASS.


CLASS zcl_bs_demo_oo_factory IMPLEMENTATION.
  METHOD create.
    IF double IS INITIAL.
      RETURN NEW zcl_bs_demo_oo_private( ).
    ELSE.
      RETURN double.
    ENDIF.
  ENDMETHOD.
ENDCLASS.

 

Finally, don't forget to activate both objects (Injector and Factory).

 

Test

We have now prepared everything for our test. Let's look at the current scenario and two ways we can use the Injector effectively.

 

Function

Our Injector is now prepared so that we can use it to inject a test double into the Factory, which we will then use in the unit test. This way, we only test the behavior of our VALIDATE_TIMESTAMP method and no longer the dependency on its implementation in the Timestamp class.

 

Local Class

As a first option, we define a local helper class where we implement the interface. Since we have marked the class as FOR TESTING, we can use PARTIALLY IMPLEMENTED and do not have to implement all methods from the interface.

CLASS lhc_double DEFINITION FOR TESTING.
  PUBLIC SECTION.
    INTERFACES zif_bs_demo_oo_interface PARTIALLY IMPLEMENTED.
ENDCLASS.


CLASS lhc_double IMPLEMENTATION.
  METHOD zif_bs_demo_oo_interface~get_timestamp.
    RETURN '20991231063000.0000000'.
  ENDMETHOD.
ENDCLASS.

 

Before we execute our test code, we use the injector, create a new instance of our helper class, and pass the instance. The injector then sets the DOUBLE in the factory, which is used for the unit test.

zcl_bs_demo_oo_injector=>inject_double( NEW lhc_double( ) ).

 

Test Double Framework

As a second option, we can use the Test Double Framework. With this option, we don't need the local implementation with the interface, but we do have to perform a few steps to prepare the double. You can find more information about the framework in this article.

DATA(double) = CAST zif_bs_demo_oo_interface( cl_abap_testdouble=>create( 'zif_bs_demo_oo_interface' ) ).
cl_abap_testdouble=>configure_call( double )->ignore_all_parameters( )->returning( '20991231063000.0000000' ).
double->get_timestamp( ).

 

As a final step, we pass the created and prepared double to the injector and run our test again.

zcl_bs_demo_oo_injector=>inject_double( double ).

 

Result

Both unit tests are now running and we reach the timestamp sooner and more often to get our unit tests to pass.

 

Complete Example

You can find the complete source code of the examples in our corresponding GitHub repository. You will find most of the coding in this article, but we have only shown the most important parts, especially regarding execution and use.

 

Conclusion

In this article, we wanted to introduce the injector and show you how you can use it simply and effectively in future projects to build testable code and make it available to other developers.


Included topics:
OOABAP OOInjector
Comments (0)



And further ...

Are you satisfied with the content of the article? We post new content in the ABAP area every Tuesday and Friday and irregularly in all other areas. Take a look at our tools and apps, we provide them free of charge.


ADT - Metadata Wizard [MIA]

Category - ABAP

In this article, we'll take a look at the Metadata Wizard and how it might simplify your life when creating UI annotations in RAP in the future.

01/16/2026

030: Software-Heroes - My Community

Category - YouTube

Do you want to stay up-to-date with the latest ABAP and SAP knowledge without having to search through every blog individually? My Community brings all community content into a mini-app that you can customize to your liking, so you never miss any news.

12/22/2025

ABAP Tools - IDE Actions (Table)

Category - ABAP

How do you actually create a table and edit it in the IDE Action? Let's look at the input options and how you can ultimately work with the data.

12/09/2025

ABAP Tools - IDE Actions (Side Effects)

Category - ABAP

How can we automatically update information on the UI when something happens with the IDE action? Let's take a closer look at the side effects.

11/18/2025

ABAP Tools - IDE Actions (Value Help)

Category - ABAP

Let's take a detailed look at how we can create a value help for our input for our IDE action in ADT. We'll examine several possibilities and dependencies.

11/11/2025