creating test-doubles for AMDP classes
AMDP classes wrap database procedures written in SQLScript or Native SQL.
The table entities used in Open SQL statments can be replaced by test-doubles with the Open SQL replacement service. Table entities used in SQLScript or Native SQL statements can’t be replaced with this service. If the AMDP class doesn’t implement a CDS table function, we can’t use the CDS Test Double Framework. So a suitable solution is the ABAP Test Double Framework.
AMDP classes are in principle normal ABAP classes with a few particularities:
- They were thought for database procedures, which can’t be easily implemented in Open SQL or in ABAP-CDS
- They must implement a database specific tag interface (
IF_AMDP_MARKER_+ suffix for database system):
IF_AMDP_MARKER_HDBfor HANA databases
This concept can be expanded to other database systems, but HANA is the only supported database for now.
- They contain AMDP methods, which implement the database procedures
AMDP methods require a specific parameter interface:
- only elementary data types or tables types with a elementary row type are supported
- parameters must be passed by value
- no return parameters can be declared
- the implementation can’t be empty
A sample AMDP class can be seen below.
INTERFACE zif_flight_accessor PUBLIC . METHODS increase_price IMPORTING VALUE(clnt) TYPE sy-mandt VALUE(carrid) TYPE s_carr_id VALUE(connid) TYPE s_conn_id VALUE(fldate) TYPE s_date VALUE(increment) TYPE sflight-price. ENDINTERFACE.
CLASS zflight_accessor DEFINITION PUBLIC FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES zif_flight_accessor . INTERFACES if_amdp_marker_hdb. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zflight_accessor IMPLEMENTATION. METHOD zif_flight_accessor~increase_price BY DATABASE PROCEDURE FOR HDB LANGUAGE SQLSCRIPT USING sflight. update sflight set price = price + :increment where mandt = :clnt and carrid = :carrid and connid = :connid and fldate = :fldate; ENDMETHOD. ENDCLASS.
AMDP methods can be called like any other method. For this reason, the AMDP method
INCREASE_PRICE in class
ZFLIGHT_ACCESSOR is packed behind an interface. When an AMDP method can be called like any other method, it’s possible to create a test-double with the ABAP Test Double Framework.
A simple test-double for
INCREASE_PRICE is created like this:
increase_price_test_double ?= cl_abap_testdouble=>create( object_name = 'ZIF_FLIGHT_ACCESSOR' ). cl_abap_testdouble=>configure_call( increase_price_test_double )->and_expect( )->is_called_once( ). increase_price_test_double->increase_price( clnt = sy-mandt increment = 10 carrid = 'TG' connid = 924 fldate = '20200420' ).
This creates a mock with the expectation
INCREASE_PRICE is called once with the parameters:
increment = 10
carrid = 'TG'
connid = 924
fldate = '20200420'
The expectation can be verified with the statement
cl_abap_testdouble=>verify_expectations( increase_price_test_double ).
Instead of replacing a table entity with the OpenSQL replacement service, we can replace the AMDP class by an test-double. This approach doesn’t cover the SQL statements, but it can be helpful for creating deterministic unit tests.