ABAP Unit & Test Doubles
Test classes are local classes in the test classes include of a global class (or in a report) marked FOR TESTING:
37.1 ABAP Unit basics
Test classes are local classes in the test classes include of a global class (or in a report) marked FOR TESTING:
Run with Ctrl+Shift+F10 in ADT or *Module Test* (Ctrl+Shift+F10/menu) in SAP GUI; coverage via *Run As → ABAP Unit Test With Coverage*.
CLASS ltc_calculator DEFINITION FINAL FOR TESTING
DURATION SHORT
RISK LEVEL HARMLESS.
PRIVATE SECTION.
DATA mo_cut TYPE REF TO zcl_calculator. " class under test
METHODS setup.
METHODS add_two_numbers FOR TESTING.
METHODS divide_by_zero_raises FOR TESTING.
ENDCLASS.
CLASS ltc_calculator IMPLEMENTATION.
METHOD setup.
mo_cut = NEW #( ).
ENDMETHOD.
METHOD add_two_numbers.
cl_abap_unit_assert=>assert_equals( exp = 5 act = mo_cut->add( iv_a = 2 iv_b = 3 )
msg = 'Addition failed' ).
ENDMETHOD.
METHOD divide_by_zero_raises.
TRY.
mo_cut->divide( iv_a = 1 iv_b = 0 ).
cl_abap_unit_assert=>fail( 'Exception expected' ).
CATCH zcx_division_by_zero.
" expected
ENDTRY.
ENDMETHOD.
ENDCLASS.37.2 Fixture methods and assertions
class_setup (static) Once before all tests of the class Before each test method After each test method class_teardown (static) Once after all tests
Assertions (CL_ABAP_UNIT_ASSERT): assert_equals, assert_differs, assert_true, assert_false, assert_initial, assert_not_initial, assert_bound, assert_not_bound, assert_subrc, assert_char_cp, assert_table_contains, assert_number_between, fail, skip. Test attributes: RISK LEVEL HARMLESS | DANGEROUS | CRITICAL, DURATION SHORT | MEDIUM | LONG.
37.3 Dependency injection and test doubles
Design for testability: depend on interfaces and inject implementations.
Test with a hand-written fake or the ABAP OO test double framework:
INTERFACE zif_order_repository.
METHODS get_order IMPORTING iv_id TYPE zorders-order_id RETURNING VALUE(rs_order) TYPE zorders.
ENDINTERFACE.
CLASS zcl_order_pricing DEFINITION PUBLIC CREATE PUBLIC.
PUBLIC SECTION.
METHODS constructor IMPORTING io_repo TYPE REF TO zif_order_repository OPTIONAL.
METHODS discounted_amount IMPORTING iv_id TYPE zorders-order_id
RETURNING VALUE(rv_amount) TYPE zorders-amount.
PRIVATE SECTION.
DATA mo_repo TYPE REF TO zif_order_repository.
ENDCLASS.
CLASS zcl_order_pricing IMPLEMENTATION.
METHOD constructor.
mo_repo = COND #( WHEN io_repo IS BOUND THEN io_repo ELSE NEW zcl_order_repository_db( ) ).
ENDMETHOD.
METHOD discounted_amount.
DATA(ls_order) = mo_repo->get_order( iv_id ).
rv_amount = COND #( WHEN ls_order-amount > 1000 THEN ls_order-amount * '0.9' ELSE ls_order-amount ).
ENDMETHOD.
ENDCLASS.METHOD big_orders_get_discount.
DATA lo_repo TYPE REF TO zif_order_repository.
lo_repo ?= cl_abap_testdouble=>create( 'ZIF_ORDER_REPOSITORY' ).
cl_abap_testdouble=>configure_call( lo_repo )->returning( VALUE zorders( amount = 2000 ) ).
lo_repo->get_order( '0000000001' ). " records the configuration
DATA(lo_cut) = NEW zcl_order_pricing( lo_repo ).
cl_abap_unit_assert=>assert_equals( exp = 1800 act = lo_cut->discounted_amount( '0000000001' ) ).
ENDMETHOD.37.4 Test environments for database, CDS, and more
ABAP SQL test double Database tables / views used in ABAP SQL CDS test double Dependencies of a CDS view under test Function module test double RAP BO test double
CL_BOTD_TXBUFDBL_BO_TEST_ENV, CL_BOTD_MOCKEMLAPI_BO_TEST_ENV EML calls to RAP BOs AUTHORITY-CHECK results Test seams (legacy code) TEST-SEAM / TEST-INJECTION Replace code blocks in tests (zorders_tt stands for a table type of ZORDERS.)
CLASS ltc_repo DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS.
PRIVATE SECTION.
CLASS-DATA go_env TYPE REF TO if_osql_test_environment.
CLASS-METHODS class_setup.
CLASS-METHODS class_teardown.
METHODS setup.
METHODS reads_order FOR TESTING.
ENDCLASS.
CLASS ltc_repo IMPLEMENTATION.
METHOD class_setup.
go_env = cl_osql_test_environment=>create( i_dependency_list = VALUE #( ( 'ZORDERS' ) ) ).
ENDMETHOD.
METHOD class_teardown.
go_env->destroy( ).
ENDMETHOD.
METHOD setup.
go_env->clear_doubles( ).
DATA(lt_data) = VALUE zorders_tt( ( order_id = '0000000001' amount = 50 ) ).
go_env->insert_test_data( lt_data ).
ENDMETHOD.
METHOD reads_order.
DATA(ls_order) = NEW zcl_order_repository_db( )->zif_order_repository~get_order( '0000000001' ).
cl_abap_unit_assert=>assert_equals( exp = 50 act = ls_order-amount ).
ENDMETHOD.
ENDCLASS.