This is a test message to test the length of the message box.
Login
ABAP Unit TDF Authority check
Created by Software-Heroes

ABAP Unit - TDF (Authority check)

213

Can you actually mock an authorization check? In this article, we'll look at the test double for authority checks.



In this article, we will create a new authorization object (ABAP Cloud), implement a method with an authorization check, and then mock the actual check for testing.

 

Introduction

Authorization checks are standard in ABAP development and are intended to ensure that not everyone has access to certain functionalities in the system. However, until now, this topic has not been well covered in ABAP unit tests, and testing various authorization checks has not always been easy. There is now a test duplicate for mocking the exam.

 

Preparation

Before we can begin the test, we need to do some preparatory work, which is described in this chapter.

 

Authorization Object

In the first step, we create a new authorization object. With ABAP Cloud, you can do this via the ABAP Development Tools by searching the objects.

 

As before, the name length is limited to 10 characters, so unfortunately we still can't work with descriptive names here. We'll name the object ZBS_TDFCHK.

 

After creation, we receive an input mask for the new authorization object. In the upper part, the object for Cloud Development is selected. The activity (ACTVT) has been automatically supplemented with some characteristics. Here, however, we only need 02 and 03 as variants for our test.

 

Class

Then we define a class that contains a method with the authorization check. So that we can test different activities, we create constants. The method performs an authorization check and returns a Boolean value for the result.

CLASS zcl_bs_demo_tdf_auth DEFINITION
  PUBLIC FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    TYPES auth_activity TYPE c LENGTH 2.

    CONSTANTS: BEGIN OF activities,
                 change  TYPE auth_activity VALUE '02',
                 display TYPE auth_activity VALUE '03',
               END OF activities.

    METHODS has_authority
      IMPORTING activity      TYPE auth_activity
      RETURNING VALUE(result) TYPE abap_boolean.
ENDCLASS.


CLASS zcl_bs_demo_tdf_auth IMPLEMENTATION.
  METHOD has_authority.
    AUTHORITY-CHECK OBJECT 'ZBS_TDFCHK'
                    ID 'ACTVT' FIELD activity.

    RETURN xsdbool( sy-subrc = 0 ).
  ENDMETHOD.
ENDCLASS.

 

Assignment

As the final step in the preparation, we need to assign permissions to our user. Currently, the framework can only restrict permissions; we cannot grant ourselves new permissions. This is therefore an important point for testing and use. In a cloud system, we assign the permission object via an IAM app and a business catalog. On-premises, you extend a PFCG role or create a new one and assign it to yourself.

 

Test Double

The basics are now in place in the system, so we'll begin by implementing the test class and setting up the test double.

 

Basic Structure

In the first step, we create a basic configuration and validate that we have all the permissions by default. Since we've just created the object, it shouldn't exist in any role yet, but we assigned it to ourselves with the last step. We'll create our test instance CUT for each unit test using the Setup method. More details on the flow and the basics can be found in this article.

CLASS ltc_authority DEFINITION FINAL
  FOR TESTING RISK LEVEL HARMLESS DURATION SHORT.

  PRIVATE SECTION.
    DATA cut TYPE REF TO zcl_bs_demo_tdf_auth.

    METHODS setup.
    METHODS change_auth      FOR TESTING RAISING cx_static_check.
    METHODS display_auth     FOR TESTING RAISING cx_static_check.
ENDCLASS.


CLASS ltc_authority IMPLEMENTATION.
  METHOD setup.
    cut = NEW #( ).
  ENDMETHOD.


  METHOD change_auth.
    DATA(result) = cut->has_authority( cut->activities-change ).

    cl_abap_unit_assert=>assert_true( result ).
  ENDMETHOD.


  METHOD display_auth.
    DATA(result) = cut->has_authority( cut->activities-display ).

    cl_abap_unit_assert=>assert_true( result ).
  ENDMETHOD.
ENDCLASS.

 

Setting Up the Double

In the next step, we want to set up and use the double. To do this, we use the CL_AUNIT_AUTHORITY_CHECK class to create a controller with which we can control our unit test. The class contains various methods with which we can restrict permissions or, for example, define expectations.

 

To do this, we create a controller in CLASS_SETUP to make it available for all unit tests.

METHOD class_setup.
  auth_controller = cl_aunit_authority_check=>get_controller( ).
ENDMETHOD.

 

To ensure that the controller does not affect tests with real permissions, we reset the controller after each unit test using the teardown method. 

METHOD teardown.
  auth_controller->reset( ).
ENDMETHOD.

 

If we now want to restrict the permissions, we first define the new permissions. We create an object set for this internal table using the CREATE_AUTH_OBJECT_SET method. Finally, we pass the set to the controller to restrict the permissions.

METHOD set_only_display_auth.
  DATA(auth_display) = VALUE cl_aunit_auth_check_types_def=>role_auth_objects(
      ( object         = 'ZBS_TDFCHK'
        authorizations = VALUE #( ( VALUE #( ( fieldname   = 'ACTVT'
                                               fieldvalues = VALUE #( ( lower_value = '03' ) )  ) ) ) ) ) ).

  DATA(auth_objectset) = cl_aunit_authority_check=>create_auth_object_set(
      VALUE cl_aunit_auth_check_types_def=>user_role_authorizations( ( role_authorizations = auth_display ) ) ).

  auth_controller->restrict_authorizations_to( auth_objectset ).
ENDMETHOD.

 

By RESET, we ensure that the next unit test has full permissions again. To do this, we define additional test methods to check the existing permissions and whether the permissions are still restricted.

 

Logs

After executing the test, we can have the execution log returned via the controller. We can perform further checks using this object. This is especially useful if the result of the method does not reflect the permission check.

DATA(execution_log) = auth_controller->get_auth_check_execution_log( ).

 

The log offers us various methods to obtain execution information. For example, using GET_EXECUTION_STATUS, we receive information about the number of checks executed and which ones failed.

 

If we look at the failed checks, we find the last check that failed for our user. This gives us another opportunity to monitor the tests performed.

 

Complete Example

Here you can find the complete example of the unit test. You can find the global class in the Preparation chapter; we have not included it again.

CLASS ltc_authority DEFINITION FINAL
  FOR TESTING RISK LEVEL HARMLESS DURATION SHORT.

  PRIVATE SECTION.
    CLASS-DATA auth_controller TYPE REF TO if_aunit_auth_check_controller.

    DATA cut TYPE REF TO zcl_bs_demo_tdf_auth.

    CLASS-METHODS class_setup.

    METHODS setup.
    METHODS teardown.

    METHODS set_only_display_auth
      RAISING cx_abap_auth_check_exception.

    METHODS change_auth         FOR TESTING RAISING cx_static_check.
    METHODS display_auth        FOR TESTING RAISING cx_static_check.
    METHODS double_without_auth FOR TESTING RAISING cx_static_check.
    METHODS double_with_auth    FOR TESTING RAISING cx_static_check.
    METHODS check_logs          FOR TESTING RAISING cx_static_check.
ENDCLASS.


CLASS ltc_authority IMPLEMENTATION.
  METHOD class_setup.
    auth_controller = cl_aunit_authority_check=>get_controller( ).
  ENDMETHOD.


  METHOD setup.
    cut = NEW #( ).
  ENDMETHOD.


  METHOD teardown.
    auth_controller->reset( ).
  ENDMETHOD.


  METHOD change_auth.
    DATA(result) = cut->has_authority( cut->activities-change ).

    cl_abap_unit_assert=>assert_true( result ).
  ENDMETHOD.


  METHOD display_auth.
    DATA(result) = cut->has_authority( cut->activities-display ).

    cl_abap_unit_assert=>assert_true( result ).
  ENDMETHOD.


  METHOD double_without_auth.
    set_only_display_auth( ).

    DATA(result) = cut->has_authority( cut->activities-change ).

    cl_abap_unit_assert=>assert_false( result ).
  ENDMETHOD.


  METHOD double_with_auth.
    set_only_display_auth( ).

    DATA(result) = cut->has_authority( cut->activities-display ).

    cl_abap_unit_assert=>assert_true( result ).
  ENDMETHOD.


  METHOD check_logs.
    set_only_display_auth( ).

    DATA(result) = cut->has_authority( cut->activities-change ).

    DATA(execution_log) = auth_controller->get_auth_check_execution_log( ).

    execution_log->get_execution_status( IMPORTING failed_execution = DATA(failed_execution) ).

    cl_abap_unit_assert=>assert_false( result ).
    cl_abap_unit_assert=>assert_equals( exp = 1
                                        act = lines( failed_execution ) ).
  ENDMETHOD.


  METHOD set_only_display_auth.
    DATA(auth_display) = VALUE cl_aunit_auth_check_types_def=>role_auth_objects(
        ( object         = 'ZBS_TDFCHK'
          authorizations = VALUE #( ( VALUE #( ( fieldname   = 'ACTVT'
                                                 fieldvalues = VALUE #( ( lower_value = '03' ) )  ) ) ) ) ) ).

    DATA(auth_objectset) = cl_aunit_authority_check=>create_auth_object_set(
        VALUE cl_aunit_auth_check_types_def=>user_role_authorizations( ( role_authorizations = auth_display ) ) ).

    auth_controller->restrict_authorizations_to( auth_objectset ).
  ENDMETHOD.
ENDCLASS.

 

Conclusion

Using the double for authorization checks, we can simulate missing authorizations and thus better test the behavior of our logic. For security reasons, no additional authorizations can be granted, although this also makes sense.

 

Source:
Release - ABAP Feature Matrix
SAP Help - Managing Dependencies on ABAP Authority Checks


Included topics:
ABAP UnitABAPUnit TestsTest-Double-FrameworkAuthorization
Comments (0)



And further ...

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


BTP - ABAP Unit Runner

Category - ABAP

How can you regularly run your ABAP unit tests on the ABAP environment and have the results sent to you? There is currently no standard for this.

02/11/2025

ABAP Unit - Test execution

Category - ABAP

What options are there for executing ABAP Unit and what hidden functions might you not know about? More details about the different modes in this article.

06/25/2024

ABAP Unit - Automation

Category - ABAP

When do objects break during development and what side effects can adjustments have? In this article we take a closer look at the topic.

01/05/2024

ABAP Unit - TDF (Function Double)

Category - ABAP

In this article, let's take a look at how we can deal with function modules as dependencies without testing them as well.

04/07/2023

RAP - ABAP Unit (Service)

Category - ABAP

How do you actually test the service of an interface or RAP app automatically? In this article we look at unit tests for OData services.

01/20/2023