Zuerst einmal: Das Ganze findet sich auch auf GitHub:
Für alle die sich schnell etwas Inspiration holen möchten. Hier die interessanten Codingausschnitte.
Inhaltsverzeichnis
Datenmodell Kopf-Entität Session
@AccessControl.authorizationCheck: #CHECK
@Metadata.allowExtensions: true
@EndUserText.label: 'CDS View forSession'
define root view entity ZR_AC_SESSIONTP
as select from zzt_ac_session
composition [0..*] of ZR_AC_SPEAKERTP as _Speaker
association [0..1] to ZI_AC_ACCEPTED_VH as _AcceptedStatus on $projection.Accepted = _AcceptedStatus.Accepted
{
key session_uuid as SessionUUID,
title as Title,
language as Language,
abstract as Abstract,
duration as Duration,
focus_area as FocusArea,
session_level as SessionLevel,
@Semantics.eMail.address: true
mail as Mail,
accepted as Accepted,
@Semantics.systemDateTime.createdAt: true
created_at as CreatedAt,
@Semantics.user.createdBy: true
created_by as CreatedBy,
@Semantics.user.lastChangedBy: true
last_changed_by as LastChangedBy,
last_changed_at as LastChangedAt,
@Semantics.systemDateTime.localInstanceLastChangedAt: true
local_last_changed_at as LocalLastChangedAt,
case
when accepted = 'X' then 3
else 2
end as CriticalityAccepted,
_Speaker,
_AcceptedStatus
}
Datenmodell Kind-Entität Speaker
@AccessControl.authorizationCheck: #CHECK
@Metadata.allowExtensions: true
@EndUserText.label: 'CDS View forSpeaker'
define view entity ZR_AC_SPEAKERTP
as select from zzt_ac_speaker
association to parent ZR_AC_SESSIONTP as _Session on $projection.ParentUUID = _Session.SessionUUID
{
key speaker_uuid as SpeakerUUID,
parent_uuid as ParentUUID,
speaker_name as SpeakerName,
speaker_short_bio as SpeakerShortBio,
speaker_profile as SpeakerProfile,
speaker_job_descr as SpeakerJobDescr,
speaker_employer as SpeakerEmployer,
speaker_webpage as SpeakerWebpage,
socialmed as Socialmed,
picture as Picture,
@Semantics.systemDateTime.localInstanceLastChangedAt: true
local_last_changed_at as LocalLastChangedAt,
_Session
}
BDEF Session
...
validation validateMail on save { field Mail; create; update; }
validation validateMailEnding on save { field Mail; create; update; }
action SetSessionAccepted result [1] $self;
...
BDEF Speaker
...
determination autoTwitterHandle on modify { field SpeakerWebpage; }
...
Behaviour Implementation Session (Auszug der Methoden)
...
METHOD validateMail.
"Fetch entered mail address for validation with EML
READ ENTITIES OF zr_ac_sessiontp IN LOCAL MODE
ENTITY Session
FIELDS ( Mail ) WITH CORRESPONDING #( keys )
RESULT DATA(mailAddresses).
LOOP AT mailAddresses INTO DATA(mailAddress).
"Simplest validation to check the format of the mail address
IF mailaddress-Mail NA '@' OR mailaddress-Mail NA '.'.
"Return validation error
APPEND VALUE #( %tky = mailaddress-%tky ) TO failed-session.
"Report text for user
APPEND VALUE #( %tky = mailAddress-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = 'E-Mail adress invalid format'
)
%element-Mail = if_abap_behv=>mk-on ) TO reported-session.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD validateMailEnding.
DATA mailCorrect TYPE xsdboolean.
"Fetch entered mail address for validation with EML
READ ENTITIES OF zr_ac_sessiontp IN LOCAL MODE
ENTITY Session
FIELDS ( Mail ) WITH CORRESPONDING #( keys )
RESULT DATA(mailAddresses).
"Reads the customized valid mail endings from database table -> dependency
SELECT mail_ending FROM zzt_ac_validmail INTO TABLE @DATA(valid_mail_endings).
LOOP AT mailAddresses INTO DATA(mailAddress).
LOOP AT valid_mail_endings INTO DATA(valid_mail_ending).
"check if mail ends with a valid ending from database table
IF mailaddress-Mail CP |*{ valid_mail_ending-mail_ending }|.
mailcorrect = abap_true.
ENDIF.
ENDLOOP.
"ends not with a valid mail provider -> error
IF mailcorrect = abap_false.
"Return validation error
APPEND VALUE #( %tky = mailaddress-%tky ) TO failed-session.
"Report text for user
APPEND VALUE #( %tky = mailAddress-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = 'E-Mail adress invalid endig (not known provider)'
)
%element-Mail = if_abap_behv=>mk-on ) TO reported-session.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD SetSessionAccepted.
MODIFY ENTITIES OF zr_ac_sessiontp IN LOCAL MODE
ENTITY Session
UPDATE FROM VALUE #( FOR key IN keys
( SessionUUID = key-sessionuuid
Accepted = abap_true
%control-accepted = if_abap_behv=>mk-on ) )
FAILED failed
REPORTED reported.
"Read changed data for action result
READ ENTITIES OF zr_ac_sessiontp IN LOCAL MODE
ENTITY Session
ALL FIELDS WITH
CORRESPONDING #( keys )
RESULT DATA(sessions).
"Send Mail to Speaker
LOOP AT sessions INTO DATA(session).
result = VALUE #( BASE result
( %tky = session-%tky
%param = session ) ).
ENDLOOP.
ENDMETHOD.
Behaviour Implementation Speaker(Auszug der Methoden)
...
METHOD autoTwitterHandle.
DATA twitter_handle TYPE ze_abapconf_speaker_socialmed.
" Read travel instances of the transferred keys
READ ENTITIES OF zr_ac_sessiontp IN LOCAL MODE
ENTITY Speaker
FIELDS ( speakerwebpage socialmed )
WITH CORRESPONDING #( keys )
RESULT DATA(speakers)
" TODO: variable is assigned but never used (ABAP cleaner)
FAILED DATA(read_failed).
" Check if Social Media Handle is already set
DELETE speakers WHERE Socialmed IS NOT INITIAL.
IF speakers IS INITIAL.
RETURN.
ENDIF.
LOOP AT speakers INTO DATA(speaker).
" Check if Webpage is a Twitter Profile
IF speaker-SpeakerWebpage CA 'twitter.com/'.
twitter_handle = |@{ match( val = speaker-SpeakerWebpage
regex = '([^\/]+$)' ) }|.
MODIFY ENTITIES OF zr_ac_sessiontp IN LOCAL MODE
ENTITY Speaker
UPDATE SET FIELDS
WITH VALUE #( ( %tky = speaker-%tky Socialmed = twitter_handle ) )
REPORTED DATA(update_reported).
" Set the changing parameter
reported = CORRESPONDING #( DEEP update_reported ).
ENDIF.
ENDLOOP.
ENDMETHOD.
Testklasse Session
CLASS ltc_session DEFINITION FINAL FOR TESTING
DURATION SHORT
RISK LEVEL HARMLESS.
PRIVATE SECTION.
CLASS-DATA: class_under_test TYPE REF TO lhc_session,
cds_test_environment TYPE REF TO if_cds_test_environment,
sql_test_environment TYPE REF TO if_osql_test_environment.
CLASS-METHODS:
"! Instantiate class under test and setup test double frameworks
class_setup,
"! Destroy test environments and test doubles
class_teardown.
METHODS:
"! Reset test doubles
setup,
"! Reset transactional buffer
teardown,
"! Test Validation of correct mail address
validateCorrectMail FOR TESTING,
"! Test Validation of correct mail address
validateIncorrectMail FOR TESTING,
"! Test Validation of correct mail address
validateCorrectMailEnding FOR TESTING,
"! Test accept a Session Action
acceptSession FOR TESTING.
ENDCLASS.
CLASS ltc_session IMPLEMENTATION.
METHOD class_setup.
CREATE OBJECT class_under_test FOR TESTING.
cds_test_environment = cl_cds_test_environment=>create( i_for_entity = 'ZR_AC_SESSIONTP' ).
sql_test_environment = cl_osql_test_environment=>create( i_dependency_list = VALUE #( ( 'ZZT_AC_VALIDMAIL' ) ) ).
ENDMETHOD.
METHOD setup.
cds_test_environment->clear_doubles( ).
sql_test_environment->clear_doubles( ).
ENDMETHOD.
METHOD teardown.
ROLLBACK ENTITIES.
ENDMETHOD.
METHOD class_teardown.
cds_test_environment->destroy( ).
sql_test_environment->destroy( ).
ENDMETHOD.
METHOD validateCorrectMail.
" Declare required structures
DATA failed TYPE RESPONSE FOR FAILED LATE zr_ac_sessiontp.
DATA reported TYPE RESPONSE FOR REPORTED LATE zr_ac_sessiontp.
" Fill in test data
DATA session_mock_data TYPE STANDARD TABLE OF zzt_ac_session.
session_mock_data = VALUE #( ( session_uuid = cl_system_uuid=>if_system_uuid_static~create_uuid_x16( ) title = 'Testtitel' Abstract = 'Eine Test Session' Session_Level = 'Basics'
mail = 'mail@test.de' Language = 'English' Focus_Area = 'ABAP Restful Application Programming Model (RAP)' ) ).
cds_test_environment->insert_test_data( session_mock_data ).
" Call method to be tested
class_under_test->validatemail(
EXPORTING
keys = CORRESPONDING #( session_mock_data MAPPING SessionUUID = session_uuid )
CHANGING
failed = failed
reported = reported
).
" Check for content in failed and reported
cl_abap_unit_assert=>assert_initial( msg = 'failed' act = failed ).
cl_abap_unit_assert=>assert_initial( msg = 'reported' act = reported ).
ENDMETHOD.
METHOD validateincorrectmail.
" Declare required structures
DATA failed TYPE RESPONSE FOR FAILED LATE zr_ac_sessiontp.
DATA reported TYPE RESPONSE FOR REPORTED LATE zr_ac_sessiontp.
" Fill in test data
DATA session_mock_data TYPE STANDARD TABLE OF zzt_ac_session.
session_mock_data = VALUE #( ( session_uuid = cl_system_uuid=>if_system_uuid_static~create_uuid_x16( )
title = 'Testtitel'
Abstract = 'Eine Test Session'
Session_Level = 'Basics'
mail = 'ichBinKeineMail'
Language = 'English'
Focus_Area = 'ABAP Restful Application Programming Model (RAP)' ) ).
cds_test_environment->insert_test_data( session_mock_data ).
" Call method to be tested
class_under_test->validatemail(
EXPORTING keys = CORRESPONDING #( session_mock_data MAPPING SessionUUID = session_uuid )
CHANGING failed = failed
reported = reported ).
" Check for content in failed and reported
cl_abap_unit_assert=>assert_not_initial( msg = 'failed' act = failed ).
cl_abap_unit_assert=>assert_not_initial( msg = 'reported' act = reported ).
ENDMETHOD.
METHOD validatecorrectmailending.
" Declare required structures
DATA failed TYPE RESPONSE FOR FAILED LATE zr_ac_sessiontp.
DATA reported TYPE RESPONSE FOR REPORTED LATE zr_ac_sessiontp.
" Fill in test data
DATA session_mock_data TYPE STANDARD TABLE OF zzt_ac_session.
session_mock_data = VALUE #( ( session_uuid = cl_system_uuid=>if_system_uuid_static~create_uuid_x16( ) title = 'Testtitel' Abstract = 'Eine Test Session' Session_Level = 'Basics'
mail = 'write@testmail.com' Language = 'English' Focus_Area = 'ABAP Restful Application Programming Model (RAP)' ) ).
cds_test_environment->insert_test_data( session_mock_data ).
"Test data for mail ending table
DATA mail_ending_mock_data TYPE STANDARD TABLE OF zzt_ac_validmail.
mail_ending_mock_data = VALUE #( ( mail_ending = '@testmail.com' ) ).
sql_test_environment->insert_test_data( mail_ending_mock_data ).
" Call method to be tested
class_under_test->validatemailending(
EXPORTING
keys = CORRESPONDING #( session_mock_data MAPPING SessionUUID = session_uuid )
CHANGING
failed = failed
reported = reported
).
" Check for content in failed and reported
cl_abap_unit_assert=>assert_initial( msg = 'failed' act = failed ).
cl_abap_unit_assert=>assert_initial( msg = 'reported' act = reported ).
ENDMETHOD.
METHOD acceptsession.
" Fill in test data
DATA session_mock_data TYPE STANDARD TABLE OF zzt_ac_session.
DATA(session_uuid) = cl_system_uuid=>if_system_uuid_static~create_uuid_x16( ).
session_mock_data = VALUE #( ( session_uuid = session_uuid title = 'Testtitel' Abstract = 'Eine Test Session' Session_Level = 'Basics'
mail = 'write@testmail.com' Language = 'English' Focus_Area = 'ABAP Restful Application Programming Model (RAP)' ) ).
cds_test_environment->insert_test_data( session_mock_data ).
" Declare required table and structures
DATA result TYPE TABLE FOR ACTION RESULT zr_ac_sessiontp\\session~SetSessionAccepted.
DATA mapped TYPE RESPONSE FOR MAPPED EARLY zr_ac_sessiontp.
DATA failed TYPE RESPONSE FOR FAILED EARLY zr_ac_sessiontp.
DATA reported TYPE RESPONSE FOR REPORTED EARLY zr_ac_sessiontp.
" Call the method to be tested
class_under_test->setsessionaccepted(
EXPORTING
keys = CORRESPONDING #( session_mock_data MAPPING SessionUUID = session_uuid )
CHANGING
result = result
mapped = mapped
failed = failed
reported = reported
).
" Check for content in mapped, failed and reported
cl_abap_unit_assert=>assert_initial( msg = 'mapped' act = mapped ).
cl_abap_unit_assert=>assert_initial( msg = 'failed' act = failed ).
cl_abap_unit_assert=>assert_initial( msg = 'reported' act = reported ).
" Check action result for fields of interest: Accepted should be X
DATA exp LIKE result.
exp = VALUE #( ( SessionUUID = session_uuid %param-SessionUUID = session_uuid %param-Accepted = 'X'
%param-Title = 'Testtitel' %param-Abstract = 'Eine Test Session' %param-SessionLevel = 'Basics'
%param-mail = 'write@testmail.com' %param-Language = 'English'
%param-FocusArea = 'ABAP Restful Application Programming Model (RAP)' ) ).
DATA act LIKE result.
act = CORRESPONDING #( result MAPPING SessionUUID = SessionUUID
( %param = %param MAPPING SessionUUID = SessionUUID
Accepted = Accepted
Title = Title
abstract = Abstract
SessionLevel = SessionLevel
mail = Mail
Language = Language
FocusArea = FocusArea
EXCEPT * )
EXCEPT * ).
cl_abap_unit_assert=>assert_equals( msg = 'action result' exp = exp act = act ).
ENDMETHOD.
ENDCLASS.
Testklasse Speaker
CLASS ltc_speaker DEFINITION FINAL FOR TESTING
DURATION SHORT
RISK LEVEL HARMLESS.
PRIVATE SECTION.
CLASS-DATA: class_under_test TYPE REF TO lhc_speaker,
cds_test_environment TYPE REF TO if_cds_test_environment.
CLASS-METHODS:
"! Instantiate class under test and setup test double frameworks
class_setup,
"! Destroy test environments and test doubles
class_teardown.
METHODS:
"! Reset test doubles
setup,
"! Reset transactional buffer
teardown,
"! Test Auto Twitter Handle
autoTwitterHandle FOR TESTING.
ENDCLASS.
CLASS ltc_speaker IMPLEMENTATION.
METHOD class_setup.
CREATE OBJECT class_under_test FOR TESTING.
cds_test_environment = cl_cds_test_environment=>create_for_multiple_cds(
i_for_entities = VALUE #( ( i_for_entity = 'ZR_AC_SeSSIONTP' )
( i_for_entity = 'ZR_AC_SPEAKERTP' ) )
).
ENDMETHOD.
METHOD setup.
cds_test_environment->clear_doubles( ).
ENDMETHOD.
METHOD teardown.
ROLLBACK ENTITIES.
ENDMETHOD.
METHOD class_teardown.
cds_test_environment->destroy( ).
ENDMETHOD.
METHOD autotwitterhandle.
" Fill in test data
DATA speaker_mock_data TYPE STANDARD TABLE OF zzt_ac_speaker.
DATA(speaker_uuid) = cl_system_uuid=>if_system_uuid_static~create_uuid_x16( ).
speaker_mock_data = VALUE #( ( speaker_uuid = speaker_uuid speaker_webpage = 'twitter.com/wachtersascha' ) ).
cds_test_environment->insert_test_data( speaker_mock_data ).
" Declare required table and structures
DATA reported TYPE RESPONSE FOR REPORTED LATE zr_ac_sessiontp.
" Call the method to be tested
class_under_test->autotwitterhandle(
EXPORTING keys = CORRESPONDING #( speaker_mock_data MAPPING SpeakerUUID = speaker_uuid )
CHANGING reported = reported ).
" Check for content in reported
cl_abap_unit_assert=>assert_initial( msg = 'reported' act = reported ).
READ ENTITIES OF zr_ac_sessiontp IN LOCAL MODE
ENTITY Speaker
FIELDS ( socialmed )
WITH VALUE #( ( SpeakerUUID = speaker_uuid ) )
RESULT DATA(speakers)
" TODO: variable is assigned but never used (ABAP cleaner)
FAILED DATA(read_failed).
cl_abap_unit_assert=>assert_equals( msg = 'action result' exp = '@wachtersascha' act = speakers[ 1 ]-Socialmed ).
ENDMETHOD.
ENDCLASS.
Integrationstest OData-Service
"!@testing SRVB:ZUI_AC_SESSION_O2
CLASS ztc_ac_session_odata DEFINITION
FOR TESTING
DURATION SHORT
RISK LEVEL HARMLESS
PUBLIC
FINAL
CREATE PUBLIC .
PRIVATE SECTION.
CLASS-DATA: o_client_proxy TYPE REF TO /iwbep/if_cp_client_proxy,
cds_test_environment TYPE REF TO if_cds_test_environment,
session_mock_data TYPE TABLE OF zzt_ac_session.
CLASS-METHODS :
class_setup RAISING cx_static_check,
class_teardown,
create_local_client_proxy
IMPORTING
service_key TYPE /iwbep/if_cp_client_proxy=>ty_s_service_key_v2
RETURNING
VALUE(client_proxy) TYPE REF TO /iwbep/if_cp_client_proxy .
METHODS:
setup,
teardown,
"! <p class="shorttext synchronized" lang="en"></p>
"! read request with filter for duration
read_sessions_with_filter FOR TESTING,
"! <p class="shorttext synchronized" lang="en"></p>
"! create a session with false mail adress
create_session_with_false_mail FOR TESTING.
ENDCLASS.
CLASS ztc_ac_session_odata IMPLEMENTATION.
METHOD class_setup.
o_client_proxy = create_local_client_proxy( VALUE #(
service_id = 'ZUI_AC_SESSION_O2'
service_version = '0001' ) ).
cds_test_environment = cl_cds_test_environment=>create_for_multiple_cds(
i_for_entities = VALUE #( ( i_for_entity = 'ZC_AC_SESSIONTP' i_select_base_dependencies = abap_true )
( i_for_entity = 'ZC_AC_SPEAKERTP' i_select_base_dependencies = abap_true ) )
).
DATA(session_uuid1) = cl_system_uuid=>if_system_uuid_static~create_uuid_x16( ).
DATA(session_uuid2) = cl_system_uuid=>if_system_uuid_static~create_uuid_x16( ).
session_mock_data = VALUE #( ( session_uuid = session_uuid1 title = 'Session Test 1' mail = 'dummy@gmail.com' abstract = 'Test' language ='German'
duration = '30' session_level = 'Basics' focus_area = 'Classic ABAP' )
( session_uuid = session_uuid2 title = 'Session Test 2' mail = 'dummy@gmail.com' abstract = 'Test' language ='English'
duration = '30' session_level = 'Basics' focus_area = 'S/4HANA' )
) .
ENDMETHOD.
METHOD setup.
cds_test_environment->clear_doubles( ).
ENDMETHOD.
METHOD teardown.
ROLLBACK ENTITIES.
ENDMETHOD.
METHOD class_teardown.
cds_test_environment->destroy( ).
ENDMETHOD.
METHOD create_local_client_proxy.
TRY.
" the Cloud version
DATA(class1) = 'CL_WEB_ODATA_CLIENT_FACTORY'.
CALL METHOD (class1)=>create_v2_local_proxy
EXPORTING
is_service_key = service_key
RECEIVING
ro_client_proxy = client_proxy.
CATCH cx_root.
ENDTRY.
IF client_proxy IS NOT BOUND.
TRY.
" the onPrem version
DATA(class2) = '/IWBEP/CL_CP_CLIENT_PROXY_FACT'.
CALL METHOD (class2)=>create_v2_local_proxy
EXPORTING
is_service_key = service_key
RECEIVING
ro_client_proxy = client_proxy.
CATCH cx_root.
ENDTRY.
ENDIF.
cl_abap_unit_assert=>assert_bound( msg = 'cannot get client proxy factory or service binding not active' act = client_proxy ).
ENDMETHOD.
METHOD read_sessions_with_filter.
TYPES duration_range TYPE RANGE OF ze_abapconf_duration.
cds_test_environment->insert_test_data( session_mock_data ).
DATA(o_session) = o_client_proxy->create_resource_for_entity_set( 'Session' ).
DATA(o_request) = o_session->create_request_for_read( ).
DATA(duration_range) = VALUE duration_range( ( sign = 'I' option = 'EQ' low = '30' ) ).
DATA(o_filter_factory) = o_request->create_filter_factory( ).
DATA(o_filter_node) = o_filter_factory->create_by_range( iv_property_path = 'DURATION'
it_range = duration_range ).
o_request->set_filter( o_filter_node ).
DATA(o_response) = o_request->execute( ).
cl_abap_unit_assert=>assert_not_initial( o_response ).
DATA response_data TYPE STANDARD TABLE OF zc_ac_sessiontp.
o_response->get_business_data( IMPORTING et_business_data = response_data ).
cl_abap_unit_assert=>assert_equals( exp = '2' act = lines( response_data ) ).
cl_abap_unit_assert=>assert_equals( exp = 'Session Test 1' act = response_data[ 1 ]-Title ).
cl_abap_unit_assert=>assert_equals( exp = 'Session Test 2' act = response_data[ 2 ]-title ).
ENDMETHOD.
METHOD create_session_with_false_mail.
DATA(o_session) = o_client_proxy->create_resource_for_entity_set( 'Session' ).
DATA(o_request) = o_session->create_request_for_create( ).
DATA(session_data) = VALUE zc_ac_sessiontp( sessionuuid = cl_system_uuid=>if_system_uuid_static~create_uuid_x16( ) title = 'Corrupted Session' mail = 'falseMail' abstract = 'Test' language ='German'
duration = '30' sessionlevel = 'Basics' focusarea = 'Classic ABAP' ).
o_request->set_business_data( session_data ).
try.
data(o_response) = o_request->execute( ).
catch /iwbep/cx_gateway.
"get error messages
DATA(o_msg_cont) = /iwbep/cl_mgw_msg_container=>get_mgw_msg_container( ).
DATA(messages) = o_msg_cont->get_messages( ).
endtry.
"check request errors -> multiple RAP validations
cl_abap_unit_assert=>assert_equals( exp = 'E-Mail adress invalid endig (not known provider)' act = messages[ 1 ]-message ).
cl_abap_unit_assert=>assert_equals( exp = 'E-Mail adress invalid format' act = messages[ 2 ]-message ).
ENDMETHOD.
ENDCLASS.
Sei der Erste der einen Kommentar abgibt