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
  public
  final
  create public .

public section.

  methods METHOD_UNDER_TEST
    importing
      !IV_EBELN type EBELN
    exporting
      !EV_ITM_COUNT type I .
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.


CLASS ZCL_TEST_FM_DEMO IMPLEMENTATION.

  METHOD METHOD_UNDER_TEST.

    IF iv_ebeln IS NOT INITIAL.

      CALL FUNCTION 'ZFM_DOC_GET_COUNT'
        EXPORTING
          ebeln = iv_ebeln
        IMPORTING
          count = ev_itm_count.

    ENDIF.

    "Further Processing Logic based on the item count

  ENDMETHOD.
ENDCLASS.

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'.

    "positive
    f_cut->method_under_test(
      EXPORTING
        iv_ebeln     =    cv_ebeln_pos
      IMPORTING
        ev_itm_count = DATA(lv_itm_count) ).

    cl_abap_unit_assert=>assert_equals(
      act   = lv_itm_count
      exp   = 2
      msg   = 'item count matched' ).

    "negative
    f_cut->method_under_test(
      EXPORTING
        iv_ebeln     =    cv_ebeln_neg
      IMPORTING
        ev_itm_count = lv_itm_count ).

    cl_abap_unit_assert=>assert_initial(
      act = lv_itm_count
      msg = 'item count is initial' ).

  ENDMETHOD.

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%20view%20of%20mocked%20FM%20object

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Ā https://www.linkedin.com/in/iheartsap/Ā for any queries.

 

Sara Sampaio

Sara Sampaio

Author Since: March 10, 2022

0 0 votes
Article Rating
Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x