Skip to Content
Technical Articles
Author's profile photo Subhajit Das

Become Function Module Independent ft. ABAP Units

Hello Colleagues,

In pursuit of making ABAP Unit Test less dependent and more independent 😊, today I have decided to write on an interesting but less explored topic which is removing function module dependency in ABAP Unit Test using TDF. This is one of the less discussed topics in abap unit test double framework.After implementing some of them and in absence of as many resources as other topics, I have decided to share my experience with a sample example and put an overview in one place.

So while implementing ABAP Units, we may have come across scenarios where the Depended-On-Componen(DOC) is a function module.

So how do you mock that and remove that dependency.Let’s see that with an example:

For the sake of demo I have created a sample function module which takes as input a document number and returns the number of items it has ( please don’t go by the use case as more focus is on the approach 😊)

I have created a method in a sample class which uses the function module and has some processing logic based on the function module’s output.

class ZCL_TEST_FM_DEMO definition
  create public .

public section.

      !IV_EBELN type EBELN
      !EV_ITM_COUNT type I .



    IF iv_ebeln IS NOT INITIAL.

          ebeln = iv_ebeln
          count = ev_itm_count.


    "Further Processing Logic based on the item count


Now in the test class I would make use of Test Double Framework specific to Function Modules to mock this FM and henceforth call the mocked instance instead of the productive one.


For this I have declared an environment variable which refers to the test double framework interface.

CLASS-DATA: fm_environment TYPE REF TO if_function_test_environment.


Then in Class-Setup method I create an instance and get the test double object.

    fm_environment = cl_function_test_environment=>create( VALUE #( ( |ZFM_DOC_GET_COUNT| ) ) ).

    DATA(fm_double) = fm_environment->get_double( |ZFM_DOC_GET_COUNT| ).


It’s time to set the input and output parameters.I create that using the create_input_configuration method and simultaneously the create_output_configuration method respectively.These configuration instances mock the actual import and export parameters of the function module.

DATA(input_data) = fm_double->create_input_configuration( )->set_importing_parameter( name = |ebeln| value = |5500000000| ).

DATA(output_data) = fm_double->create_output_configuration( )->set_exporting_parameter( name = |count| value = 2 ).


Finally I configure my test double to set the output when the same input is provided.In other words, I set the input and output expectations.

fm_double->configure_call( )->when( input_data )->then_set_output( output_data ).

That’s it as far as mocking was concerned


Now as usual, in my unit test method I call the method under test as usual and create positive and negative scenarios.

  METHOD determine_target_amount.

    CONSTANTS: cv_ebeln_pos TYPE ebeln VALUE '5500000000',
               cv_ebeln_neg TYPE ebeln VALUE '5500000001'.

        iv_ebeln     =    cv_ebeln_pos
        ev_itm_count = DATA(lv_itm_count) ).

      act   = lv_itm_count
      exp   = 2
      msg   = 'item count matched' ).

        iv_ebeln     =    cv_ebeln_neg
        ev_itm_count = lv_itm_count ).

      act = lv_itm_count
      msg = 'item count is initial' ).


What would happen is on the call of the function module, the test double framework generated function module will be called instead of the productive function module and you have the data in your control.This would make the test cases consistent across all environments and eliminate AUnit failures


Debugger view of mocked FM object


Some additional points to remember:

  • You can also set Tables and Changing parameters in the same way as exporting parameters
  • Similarly, you can also set multiple importing, tables, changing and exporting parameters
  • In the configure_call( ) method, you can also raise exceptions and ignore all input parameters and only set the output

Hope this resource was useful to some extent in bringing some relevant light on mocking Function Modules in ABAP Unit Test Classes.

Do post your comments, queries and suggestions if any on the same.

I am also available at LinkedIN atΒ for any queries.




Assigned Tags

      You must be Logged on to comment or reply to a post.
      Author's profile photo Peter Inotai
      Peter Inotai

      Hi Subhajt,

      Thank for sharing this info.

      Do you know as of which ABAP release this feature is available?

      I've checked our ABAP 7.55 system, and class CL_FUNCTION_TEST_ENVIRONMENT is not available there πŸ™



      Author's profile photo Subhajit Das
      Subhajit Das
      Blog Post Author

      Hi Peter,


      Firstly thank you so much for reading the content.

      It's available as of Release 7.56 😐




      Author's profile photo Peter Inotai
      Peter Inotai

      Thanks for the info.

      Author's profile photo Paul Hardy
      Paul Hardy

      I was aware of this. I cannot really see the benefit compared to wrapping the function module in a method which is accessed via an interface and can thus have a test double. In both cases you are hard coding the input/output values.

      If anything I was concerned that a function module test double framework might encourage people to keep creating new function modules when really - since the year 2000 - function modules are obsolete except for certain cases which OO ABAP cannot do e.g. RFC calls, calling a DYNPRO screen. And in both of those cases the function module should have no business logic, just outsource such logic to one or more classes.

      A-ha! You will say - what if I need a standard SAP function module? Well, you could wrap that module in a class but the real question is, after 22 years why SAP not eaten their own dog food and stopped the SAP standard code being dependant on function modules?

      Cheersy Cheers



      Author's profile photo Matthew Billingham
      Matthew Billingham

      I cannot really see the benefit compared to wrapping the function module in a method which is accessed via an interface and can thus have a test double.

      Me either. I wrap by external dependencies for a program in their own interface/class.

      I don't like using the cl_function_test_environment etc. classes. It seems highly risky. A programmer in the future adding a function module somewhere in the code will have to know that they need to add that FM to the test environment. While with a separate class they'll also have to know that the FM call goes there, at least if they get that right you don't have to change the test code.

      I'd only use these classes to get legacy code into a test harness.

      Author's profile photo Elmedin Dedic
      Elmedin Dedic

      Hi Paul HardyΒ ,

      I've been experimenting with this framework for the last couple of days.

      I would agree that it makes perfect sense to wrap a fm call in a class method implementing an interface, which you can then replace with a test double implemented in a standard way by implementing the corresponding interface method. Also without considering the testability such an approach (at least class method) would make sense for projects following the clean code principles.

      However in my opinion it is exactly this approach above that introduces the necessity of this td framework. What do I mean by that?

      If we introduce an additional layer of custom code by wrapping e.g. a BAPI in a class method (impl. interface) then in my opinion the only way to test this layer of custom code (even if the layer is just passing the importing parameters to the BAPI) is to effectively "spy" on the BAPI call itself, which in this td framework would mean verifying the BAPI td after the "cut" execution.

      td_bapi_that_is_wrapped->verify( input_configuration = input_params_of_our_methodΒ )->is_called_once( )

      So to summarize, this really focuses on test coverage of the additional layer of custom code itself and not replacing (stubing/mocking) the function module call to get rid of its dependency in the calling environment. For these purposes, where e.g. only a stub of the fm is needed, I agree that this td framework brings no benefit to implementing the td via an interface method.

      I'm really interested in your opinion regarding this.

      P.s. I'm aware that this really is a detail and maybe one of the last pieces in the puzzle of getting the "perfect" code coverage. The reality of most ABAPers today is probably 0% code coverage. :/