Enterprise Resource Planning Blogs by Members
Gain new perspectives and knowledge about enterprise resource planning in blog posts from community members. Share your own comments and ERP insights today!
cancel
Showing results for 
Search instead for 
Did you mean: 
paulfuchs
Explorer
Hi SAP community,

I am very excited to share my knowledge in my blog about how to implement an OData Integration Test for the "create by association scenario" and "deep create scenario" which is part of ABAP RESTful Application Programming Model. The test case in this blog will cover the BO Business Partner and its text notes.

During my daily work as a ABAP developer I have implemented lot's of ABAP Unit Tests. As a result, I asked myself how to test the OData Services in ABAP RAP for the CRUD operations in the SAP S/4HANA on premise system.

The answer is - yes it is possible!

Why it is relevant to test OData services?

  1. CDS views can contain Virtual Elements (not persisted fields within the CDS view). These fields are calculated during the runtime using ABAP classes.

  2. Ensure the OData service functionality for the CRUD operations which are implemented

  3. Ensure quality and reliability of an OData service


What is the assumption for the test case business partner notes?

There are some steps that need to be done before the integration test scenario can be implemented:

  • You have created one ABAP RAP Service for the business partner as business object

  • All relevant CDS views are exposed in the service definition (business partner consumption CDS view and the generic text CDS view for the notes)

  • the behaviour definition contains all CRUD functionality; especially for the create business partner entity and the create for the business partner notes association

  • the business partner CDS view contains a composition [0..*] of ZC_BUPA_NOTES
    as _BUPA_NOTES


How to implement this integration test for the create by association and deep create scenario?

The first step is to create a ABAP class for the OData integration test
CLASS zcl_integrationtest_bupa DEFINITION  PUBLIC FINAL CREATE PUBLIC FOR TESTING.
PUBLIC SECTION.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_integrationtest_bupa IMPLEMENTATION.
ENDCLASS.​

In the next step you need to create a local test class within your created class zcl_integrationtest_bupa.

The following code sample includes variables for the integration test scenario:

  • go_client_proxy:
    this variable is referenced to the /IWBEP/IF_CP_CLIENT_PROXY interface in ABAP Unit Test which is used to create a client proxy for testing OData services in ABAP. The purpose of this interface is to provide methods that allow you to create an instance of a client proxy for an OData service. The client proxy acts as a communication channel between the ABAP system and the OData service, enabling you to send requests and receive responses.
    By utilizing this interface, it is possible to simulate and test the interaction between an ABAP system and an OData service. This allows you to confirm the functionality, accuracy, and integration of your code that consumes the OData service.

  • go_cds_test_environment:
    this variable is referenced to the interface IF_CDS_TEST_ENVIRONMENT which is used to facilitate the testing of CDS views. 
    This interface provides methods and attributes that allow you to manipulate the test environment and perform assertions on the data retrieved from CDS views during testing.

  • go_sql_test_environment:
    this variable is referenced to the interface IF_OSQL_TEST_ENVIRONMENT which is used to facilitate the testing of database objects.
    This interface provides methods and attributes that allow you to manipulate the test environment and perform assertions on the data retrieved from database objects during testing.


"!@testing SRVB:ZUI_BUSINESSPARTNER_V2
CLASS ltc_create_bupa_notes_ba DEFINITION FINAL FOR TESTING DURATION MEDIUM RISK LEVEL HARMLESS.

PRIVATE SECTION.
TYPES:
BEGIN OF ty_entity_key,
BusinessPartnerUUID TYPE bu_partner_guid,
isactiveentity TYPE abap_boolean,
END OF ty_entity_key.

CLASS-DATA:
go_client_proxy TYPE REF TO /iwbep/if_cp_client_proxy,
go_cds_test_environment TYPE REF TO if_cds_test_environment,
go_sql_test_environment TYPE REF TO if_osql_test_environment.

METHODS:
"! Integration test for creating the the businesspartner notes with deep create
deep_create FOR TESTING RAISING cx_static_check,
"! Integration test create by association scenario for the business partner notes
cba_bupa_notes FOR TESTING RAISING cx_static_check,
"! Teardown performs rollback of the entities.
teardown RAISING cx_static_check,
"! This method is called before executing each test method in the test class.
"! It allows you to set up the necessary test data and initialize the test environment.
setup.

CLASS-METHODS:
"! Setup routine for the integration test for reading the businesspartner
"! It sets up the mocks for the CDS views and SQL tables and starts the local proxy.
class_setup RAISING cx_static_check,
"! Class teardown for the integration test for reading the BusinessPartner.
"! Here the mocks for the CDS-views and the databases are destroyed.
class_teardown RAISING cx_static_check.

ENDCLASS.

In addition to the class definition that has already been created, it is required to define the class implementation.

The local test class contains the OData Service "ZUI_BUSINESSPARTNER_V2". For this test case it is mandatory to use the OData Client Proxy to execute OData calls on the business partner BO which is exposed as an OData service.

In general by implementing unit tests it is recommended to use a helper class which handles the mocking of the data (CDS and SQL Mocks). This blog will not cover how to create these mock data. But no worries - I'll cover this topic in my next blog post 😉

The test class will then evaluate the results of these OData calls. 

Create by association scenario (CBA)

For the create by association scenario, it is necessary to navigate from the root entity (BusinessPartner) to the target entity "TO_BUPA_NOTES" (BusinessPartnerNotes)
CLASS ltc_create_bupa_notes_ba IMPLEMENTATION.

METHOD class_setup.
zcl_bp_l_bupa_test=>class_setup_helper(
IMPORTING
ei_cds_test_environment = go_cds_test_environment
ei_sql_test_environment = go_sql_test_environment ).

" Create Proxy
go_client_proxy = /iwbep/cl_cp_client_proxy_fact=>create_v2_local_proxy( VALUE #( service_id = 'ZUI_BUSINESSPARTNER_V2'
service_version = '0001' ) ).
ENDMETHOD.

METHOD setup.
zcl_bp_l_bupa_test=>prepare_testdataset_for_partner(
ii_cds_test_environment = go_cds_test_environment
ii_sql_test_environment = go_sql_test_environment ).

ENDMETHOD.

METHOD cba_bupa_notes.

DATA:
ls_business_data_response TYPE zc_bupa_notes,
ls_entity_key TYPE ty_entity_key.

FIELD-SYMBOLS: <lv_business_data_response> TYPE data.

" Navigate to the resource
ls_entity_key-BusinessPartnerUUID = zcl_bp_l_bupa_test=>cv_partner_uuid_draft.
ls_entity_key-isactiveentity = abap_false.

"create a request for the create operation

DATA(lo_resource) = go_client_proxy->create_resource_for_entity_set( 'BusinessPartner' ).
DATA(lo_resrouce_bupa_notes) = lo_resource->navigate_with_key( ls_entity_key )->navigate_to_many( 'TO_BUPA_NOTES' ).

"set the business data for the created entity
DATA(ls_data_notes_create) = VALUE zc_bupa_notes( TextId ='Z001' TextContent ='Business Partner Note'
RelObjectGuid = zcl_bp_l_bupa_test=>cv_partner_uuid_draft ).


DATA(lo_request_create) = lo_resrouce_bupa_notes->create_request_for_create( ).
lo_request_create->set_business_data( ls_data_notes_create ).

" execute the request
DATA(lo_response_create) = lo_request_create->execute( ).

ASSIGN ls_business_data_response TO <lv_business_data_response>.

lo_response_create->get_business_data( IMPORTING es_business_data = <lv_business_data_response> ).

cl_abap_unit_assert=>assert_equals( msg = 'values do not match'
exp = ls_business_data_create-TextContent
act = ls_business_data_response-TextContent ).

SELECT * FROM zbupa_text_d INTO TABLE @DATA(lt_bupanotes_draft). "#EC CI_NOWHERE

cl_abap_unit_assert=>assert_equals( msg = 'no entry in the draft table'
exp = lines( lt_bupanotes_draft )
act = '1' ).

ENDMETHOD.

METHOD teardown.
go_cds_test_environment->clear_doubles( ).
go_sql_test_environment->clear_doubles( ).
ROLLBACK ENTITIES.

ENDMETHOD.

METHOD class_teardown.
go_cds_test_environment->destroy( ).
go_sql_test_environment->destroy( ).
ENDMETHOD.

ENDCLASS.

 

Deep Create Scenario

There are important facts to mention about the deep create case for the integration test, which are different to the normal create case:

  1. The property path of the composition as part of the business partner CDS view "TO_BUPA_NOTES" must be added as child to the description node

  2. you need to call the method set_deep_business_data for the create request object


 
CLASS ltc_create_bupa_notes_ba IMPLEMENTATION.

METHOD class_setup.
zcl_bp_l_bupa_test=>class_setup_helper(
IMPORTING
ei_cds_test_environment = go_cds_test_environment
ei_sql_test_environment = go_sql_test_environment ).

" Create Proxy
go_client_proxy = /iwbep/cl_cp_client_proxy_fact=>create_v2_local_proxy( VALUE #( service_id = 'ZUI_BUSINESSPARTNER_V2'
service_version = '0001' ) ).
ENDMETHOD.

METHOD setup.
zcl_bp_l_bupa_test=>prepare_testdataset_for_partner(
ii_cds_test_environment = go_cds_test_environment
ii_sql_test_environment = go_sql_test_environment ).

ENDMETHOD.

METHOD deep_create.

TYPES: BEGIN OF ty_deep_entity,
BusinessPartnerUUID TYPE bu_partner_guid,
to_bupa_notes TYPE TABLE OF zc_bupa_notes WITH DEFAULT KEY, "#EC CI_DEFAULT_KEY
END OF ty_deep_entity.

DATA:
ls_data_notes_create TYPE zc_bupa_notes,
ls_business_data_create TYPE ty_deep_entity,
ls_business_data_response TYPE ty_deep_entity.

FIELD-SYMBOLS: <lv_business_data_response> TYPE data.

"create a request for the create operation
DATA(lo_resource) = go_client_proxy->create_resource_for_entity_set( 'BusinessPartner' ).

"set the business data for the created entity
ls_data_notes_create = VALUE #( TextId ='Z001' TextContent ='Business Partner Note'
RelObjectGuid = zcl_bp_l_bupa_test=>cv_partner_uuid_draft ).

ls_business_data_create = VALUE #(
BusinessPartnerUUID = zcl_bp_l_bupa_test=>cv_partner_uuid_draft
to_bupa_notes = VALUE #( ( ls_data_notes_create ) ) ).

DATA(lo_request_create) = lo_resource->create_request_for_create( ).
DATA(lo_cp_data_descr_node) = lo_request_create->create_data_descripton_node( ).
lo_cp_data_descr_node->add_child( iv_property_path = 'TO_BUPA_NOTES' ).

lo_request_create->set_deep_business_data(
is_business_data = ls_business_data_create
io_data_description = lo_cp_data_descr_node ).

" execute the request
DATA(lo_response_create) = lo_request_create->execute( ).

ASSIGN ls_business_data_response TO <lv_business_data_response>.

lo_response_create->get_business_data( IMPORTING es_business_data = <lv_business_data_response> ).

cl_abap_unit_assert=>assert_equals( msg = 'values do not match'
exp = ls_business_data_create-to_bupa_notes[ 1 ]-TextContent
act = ls_business_data_response-to_bupa_notes[ 1 ]-TextContent ).

SELECT * FROM zbupa_text_d INTO TABLE @DATA(lt_bupanotes_draft). "#EC CI_NOWHERE

cl_abap_unit_assert=>assert_equals( msg = 'no entry in the draft table'
exp = lines( lt_bupanotes_draft )
act = '1' ).

ENDMETHOD.

METHOD teardown.
go_cds_test_environment->clear_doubles( ).
go_sql_test_environment->clear_doubles( ).
ROLLBACK ENTITIES.

ENDMETHOD.

METHOD class_teardown.
go_cds_test_environment->destroy( ).
go_sql_test_environment->destroy( ).
ENDMETHOD.

ENDCLASS.

After that you can run your integration test as "ABAP Unit Test" (Ctrl+Shift+F12).


Related documentation:

OData Integration Tests SAP

Using Virtual Elements in CDS Projection Views

SAP Gateway Foundation (SAP_GWFND) - Local Client Proxy

I hope you have enjoyed my SAP Blog 😉

Paul
2 Comments
Labels in this area