in der die Funkitonalität gekapselt wird.lcl_app
Code: Alles auswählen.
CLASS lcl_app DEFINITION CREATE PUBLIC.
PUBLIC SECTION.
TYPES:BEGIN OF mty_output_tbl.
INCLUDE TYPE zprivatfahrten.
TYPES: error_field TYPE UPS_OD_ERROR_STATUS,
icon TYPE icon_d.
TYPES: END OF mty_output_tbl.
DATA:
"! Table to display the incoming Excel Data in the Frontend
mt_output_tbl TYPE STANDARD TABLE OF mty_output_tbl INITIAL SIZE 0,
"! Display one Single Entry of the Data <br/>
"! <br/>
"! Primarily used for handing over single entrys to the Backend for Booking
ms_privatfahrt TYPE zprivatfahrten.
METHODS:
constructor,
check_for_booking_requirements
RETURNING VALUE(rv_is_valid) TYPE abap_bool,
book_doc
RAISING
zcx_feh_exception.
PROTECTED SECTION.
DATA:
lv_rc TYPE i,
"! Internal Table for Handling imported Excel Files. <br/>
"! Data for processing is transferred to other table
mt_tbl_import TYPE STANDARD TABLE OF alsmex_tabline,
lt_privatfahrten TYPE STANDARD TABLE OF mty_output_tbl INITIAL SIZE 0,
ms_privatfahrten LIKE LINE OF lt_privatfahrten.
METHODS:
"Hier normalerweise mehr Methoden
PRIVATE SECTION.
ENDCLASS.
definiert, die diese kritischen Anweisungen überschreibt.lcl_inherited
Code: Alles auswählen.
CLASS lcl_inherited DEFINITION
INHERITING FROM lcl_app
FRIENDS ltc_test.
PUBLIC SECTION.
METHODS:
constructor,
"This Method differs in it's super method by the fact that the Booking Object is not created and called </br>
"No Data is changed in the System by this Encapsulation
book_doc REDEFINITION .
PROTECTED SECTION.
PRIVATE SECTION.
DATA:
"! In the Original Class in Method Booking, each summed and finished entry would jump off to another Object
"! <br/> This is here not possible. <br/>
"! <br/>
"! We now insert all the Values into this itab to check the results
check_sums TYPE STANDARD TABLE OF zprivatfahrten.
ENDCLASS.
CLASS lcl_inherited IMPLEMENTATION.
METHOD constructor.
super->constructor( ).
ENDMETHOD.
METHOD book_doc.
TRY.
SORT mt_output_tbl BY pernr ASCENDING.
CATCH cx_sy_dyn_table_ill_line_type
cx_sy_dyn_table_ill_comp_val
INTO cx_root.
MESSAGE cx_root->get_text( ) TYPE 'E'.
ENDTRY.
"Read 1st Line of Table for comparing
READ TABLE mt_output_tbl INDEX 1 ASSIGNING FIELD-SYMBOL(<fs_prev_entry>).
If sy-subrc <> 0.
RAISE EXCEPTION TYPE zcx_feh_exception.
ENDIF.
LOOP AT mt_output_tbl ASSIGNING FIELD-SYMBOL(<fs_entry>).
IF sy-tabix = 1. "Skip first entry, its already assigned in <fs_prev_entry>
CONTINUE.
ENDIF.
"Same pernr means more than 1 entry for the same Person
" -> Add Betrag existing entry
IF <fs_prev_entry>-pernr = <fs_entry>-pernr.
<fs_prev_entry>-betrag = <fs_prev_entry>-betrag + <fs_entry>-betrag.
ELSE. "Next different Entry
MOVE-CORRESPONDING <fs_prev_entry> TO ms_privatfahrt.
INSERT ms_privatfahrt INTO TABLE check_sums.
**********************************************************************
* Do not execute this in Test CLass
**********************************************************************
* "Booking
* go_doc = NEW #( is_privatfahrten = ms_privatfahrt iv_akont = '11111111').
*
* TRY.
* go_doc->create_doc( ).
* CATCH cx_sy_duplicate_key
* zcx_feh_invalid_input " Ungültige Input Parameter
* INTO cx_root.
* MESSAGE cx_root->get_text( ) TYPE 'S' DISPLAY LIKE 'E'.
* ENDTRY.
**********************************************************************
CLEAR <fs_prev_entry>.
<fs_prev_entry> = <fs_entry>.
ENDIF.
ENDLOOP.
ENDMETHOD.
ENDCLASS.
Code: Alles auswählen.
METHOD booking_cummulation.
CLEAR lo_cut->check_sums.
TRY.
lo_cut->book_doc( ).
CATCH zcx_fehrer_exception.
ENDTRY.
DESCRIBE TABLE lo_cut->check_sums LINES DATA(count_lines).
IF count_lines <> mc_num_entries.
cl_abap_unit_assert=>fail( msg = 'Not all Entries exist in SUM Table' ).
ENDIF.
auf itabs der Unterklasse zugreifen, werden diese nicht korrekt angezeigt und verarbeitet, ich vermute irgendetwas in der Ober/Unterklasse Beziehung ist falsch eingestellt aber ich bin gerade überfordert an was liegen könnte.lo_cut TYPE REF TO lcl_inherited
Welche Tabellen betrifft dies genau?auf itabs der Unterklasse zugreifen, werden diese nicht korrekt angezeigt und verarbeitet, ich vermute irgendetwas in der Ober/Unterklasse Beziehung ist falsch eingestellt aber ich bin gerade überfordert an was liegen könnte.
Code: Alles auswählen.
**********************************************************************
* Do not execute this in Test CLass
**********************************************************************
* "Booking
* go_doc = NEW #( is_privatfahrten = ms_privatfahrt iv_akont = '11111111').
*
* TRY.
* go_doc->create_doc( ).
* CATCH cx_sy_duplicate_key
* zcx_feh_invalid_input " Ungültige Input Parameter
* INTO cx_root.
* MESSAGE cx_root->get_text( ) TYPE 'S' DISPLAY LIKE 'E'.
* ENDTRY.
**********************************************************************
Ja da hast du natürlich Recht dass diese Herangehensweise beser ist, ich weiß nicht genau warum ich das nicht gleich gemacht habe :)jocoder hat geschrieben: ↑22.02.2021 12:44Dies könnte ja auch in eine eigene Methode ausgelagert werden und und diese neue Methode in LCL_INHERITED anstatt BOOK_DOC redefiniert werden. Dann entfällt ein Copy-Paste zwischen den Klassen LCL_APP und LCL_INHERITED. Wenn irgendjemand später die Klasse LCL_APP ändert, wird dies höchstwahrscheinlich übersehen und der Unit Test testet dann nichtmehr Logik der LCL_APP.
Diese ist ja public definiert deswegen bin ich mir auch nicht sicher warum es diese Probleme jetzt gibt.mt_output_tbl
Die zwei betreffenden Methoden sind booking_sort und booking_cummulation
Code: Alles auswählen.
class ltc_test definition for testing
duration short
risk level harmless.
public section.
CLASS-DATA:
mc_pernr_1 TYPE pernr_d VALUE '98199',
mc_pernr_2 TYPE zprivatfahrten-pernr VALUE '25175',
mc_bukrs TYPE bukrs VALUE '1000',
mc_lifnr TYPE lifnr VALUE 125258,
"! Sum of all of the Entries from the First Entrie: <strong>98199</strong>
mc_betrag_1 TYPE zprivatfahrten-betrag VALUE 17,
"! Sum of all of the Entries from the Second Entrie: <strong>98875</strong>
mc_betrag_2 LIKE mc_betrag_1 VALUE '14.5',
"! How many different Pernr were inserted
mc_num_entries TYPE i VALUE 2.
DATA: lo_cut TYPE REF TO lcl_inherited.
PRIVATE SECTION.
CLASS-METHODS:
"!Is called once before setup
class_setup,
class_teardown.
METHODS:
"! Called before every Method
setup,
"! Called after every Method
"! Mostly <strong>ROLLACK WORK</strong> is used
teardown,
get_last_name FOR TESTING RAISING cx_static_check,
get_first_name FOR TESTING RAISING cx_static_check,
get_last_name_with_wrong_pernr FOR TESTING RAISING cx_static_check,
get_kost FOR TESTING RAISING cx_static_check,
check_kred_with_wrong_input FOR TESTING RAISING cx_static_check,
check_kred FOR TESTING RAISING cx_static_check,
"! Is the Sorting of the Tabel executed correctly?
"! <br/>
"! IF not the Logic won't work
booking_sort FOR TESTING,
"! Are the Values of the different Pernr's summed up ccorrectly through the itab?
booking_cummulation FOR TESTING,
"! Set up Test Data for the Booking Procedure
"! Normally the itab should be sorted, but we check that explicitly once again
"! <br/>
"!
create_td_booking_unsorted.
ENDCLASS.
CLASS ltc_test IMPLEMENTATION.
METHOD class_setup.
ENDMETHOD.
METHOD setup.
"Generate PErsonal Data for testing
INSERT INTO pa0001 VALUES @( VALUE #( bukrs = mc_bukrs pernr = mc_pernr_1 begda = '20190101' endda = '20220101' kostl = '9999') ).
IF sy-subrc <> 0.
cl_abap_unit_assert=>abort( msg = 'Could not generate Test Data' ).
ENDIF.
INSERT INTO pa0002 VALUES @( VALUE #( pernr = mc_pernr_1 begda = '20190101' endda = '20220101' nchmc = 'Mustermann' vnamc = 'Max') ).
IF sy-subrc <> 0.
cl_abap_unit_assert=>abort( msg = 'Could not generate Test Data' ).
ENDIF.
"Generate Kreditor Data
INSERT INTO lfb1 VALUES @( VALUE #( bukrs = mc_bukrs lifnr = mc_lifnr pernr = mc_pernr_1 ) ).
IF sy-subrc <> 0.
cl_abap_unit_assert=>abort( msg = 'Could not generate Test Data in Table LFB1' ).
ENDIF.
CLEAR lo_cut.
CREATE OBJECT lo_cut TYPE lcl_inherited.
cl_abap_unit_assert=>assert_bound( act = lo_cut msg = 'Object lo_cut is not assigned').
create_td_booking_unsorted( ).
ENDMETHOD.
METHOD booking_cummulation.
CLEAR lo_cut->check_sums.
TRY.
lo_cut->book_doc( ).
CATCH zcx_fehrer_exception.
ENDTRY.
DESCRIBE TABLE lo_cut->check_sums LINES DATA(count_lines).
IF count_lines <> mc_num_entries.
cl_abap_unit_assert=>fail( msg = 'Not all Entries exist in SUM Table' ).
ENDIF.
LOOP AT lo_cut->check_sums ASSIGNING FIELD-SYMBOL(<fs_entry>).
"First Entry
IF <fs_entry>-pernr = mc_pernr_1.
IF <fs_entry>-betrag <> mc_betrag_1.
cl_abap_unit_assert=>fail( msg = 'Sum of the Amount for the First pernr was incorrect' ).
ENDIF.
ENDIF.
"2nd Entry
IF <fs_entry>-pernr = mc_pernr_2.
IF <fs_entry>-betrag <> mc_betrag_2.
cl_abap_unit_assert=>fail( msg = 'Sum of the Amount for the First pernr was incorrect' ).
ENDIF.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD booking_sort.
BREAK HuprichTo.
TRY.
lo_cut->book_doc( ).
CATCH zcx_fehrer_exception.
ENDTRY.
READ TABLE lo_cut->mt_output_tbl INDEX 1 ASSIGNING FIELD-SYMBOL(<fs_prev>).
If sy-subrc <> 0.
cl_abap_unit_assert=>fail( msg = 'Could not read First Line of Table mt_output_tbl').
ENDIF.
READ TABLE lo_cut->mt_output_tbl INDEX 1 ASSIGNING FIELD-SYMBOL(<fs_prev1>).
If sy-subrc <> 0.
cl_abap_unit_assert=>fail( msg = 'Could not read First Line of Table mt_output_tbl').
ENDIF.
If <fs_prev>-pernr <> mc_pernr_1.
cl_abap_unit_assert=>fail( msg = 'Wrong sorting Direction').
ENDIF.
LOOP AT lo_cut->mt_output_tbl ASSIGNING FIELD-SYMBOL(<fs_entry>).
IF sy-tabix = 1.
CONTINUE.
ENDIF.
if sy-tabix = 2.
If <fs_prev>-pernr <> <fs_entry>-pernr.
cl_abap_unit_assert=>fail( msg = 'Sorting was not executed correctly').
ENDIF.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD get_last_name.
TRY.
lo_cut->get_last_name( iv_pernr = mc_pernr_1 ).
CATCH zcx_fehrer_no_data INTO cx_root.
cl_abap_unit_assert=>fail( msg = 'Last Name could not be found' ) . "level = if_aunit_constants=>tolerable
ENDTRY.
ENDMETHOD.
METHOD get_last_name_with_wrong_pernr.
TRY.
lo_cut->get_last_name( iv_pernr = '07000' ).
CATCH zcx_fehrer_no_data INTO cx_root.
EXIT.
ENDTRY.
cl_abap_unit_assert=>fail( msg = '' ) . "level = if_aunit_constants=>tolerable
ENDMETHOD.
METHOD get_first_name.
TRY.
lo_cut->get_first_name( iv_pernr = mc_pernr_1 ).
CATCH zcx_fehrer_no_data INTO cx_root.
cl_abap_unit_assert=>fail( msg = 'First Name could not be found' ) . "level = if_aunit_constants=>tolerable
ENDTRY.
ENDMETHOD.
METHOD get_kost.
TRY.
lo_cut->get_kost( iv_pernr = mc_pernr_1 ).
CATCH zcx_fehrer_no_data INTO cx_root.
cl_abap_unit_assert=>fail( msg = 'KOST could not be found' ) . "level = if_aunit_constants=>tolerable
ENDTRY.
ENDMETHOD.
METHOD class_teardown.
ROLLBACK WORK.
ENDMETHOD.
METHOD teardown.
ROLLBACK WORK.
ENDMETHOD.
METHOD check_kred.
TRY.
lo_cut->get_kreditor( iv_bukrs = mc_bukrs iv_pernr = mc_pernr_1 ).
CATCH zcx_fehrer_no_data INTO cx_root.
cl_abap_unit_assert=>fail( msg = 'FAIL' ).
ENDTRY.
ENDMETHOD.
METHOD check_kred_with_wrong_input.
TRY.
lo_cut->get_kreditor( iv_bukrs = mc_bukrs iv_pernr = 10014 ).
CATCH zcx_fehrer_no_data INTO cx_root.
EXIT.
ENDTRY.
cl_abap_unit_assert=>fail( msg = 'No Exception was raised' ).
ENDMETHOD.
METHOD create_td_booking_unsorted.
CLEAR lo_cut->mt_output_tbl.
lo_cut->mt_output_tbl = VALUE #( BASE lo_cut->mt_output_tbl ( pernr = mc_pernr_1 name = 'Mustermann' bukrs = 1000 kst = '826' datum = '20210101'
von = 'GLH' nach = 'GLH' kfz_kennzeichen = 'BBB' betrag = 2 ) ).
lo_cut->mt_output_tbl = VALUE #( BASE lo_cut->mt_output_tbl ( pernr = mc_pernr_2 name = 'Frauenhofer' bukrs = 1100 kst = '1225' datum = '20210105'
von = 'GLH' nach = 'WSH' kfz_kennzeichen = 'TEST-XB-88' betrag = 14 ) ).
lo_cut->mt_output_tbl = VALUE #( BASE lo_cut->mt_output_tbl ( pernr = mc_pernr_1 name = 'Mustermann' bukrs = 1000 kst = '826' datum = '20210104'
von = 'KT' nach = 'GLH' kfz_kennzeichen = 'BBB' betrag = 6 ) ).
lo_cut->mt_output_tbl = VALUE #( BASE lo_cut->mt_output_tbl ( pernr = mc_pernr_1 name = 'Mustermann' bukrs = 1000 kst = '826' datum = '20210105'
von = 'GLH' nach = 'WSH' kfz_kennzeichen = 'BBB' betrag = 9 ) ).
lo_cut->mt_output_tbl = VALUE #( BASE lo_cut->mt_output_tbl ( pernr = mc_pernr_2 name = 'Frauenhofer' bukrs = 1100 kst = '1225' datum = '20210105'
von = 'GLH' nach = 'WSH' kfz_kennzeichen = 'TEST-XB-88' betrag = '0.5' ) ).
ENDMETHOD.
ENDCLASS.
Code: Alles auswählen.
lo_cut->mt_output_tbl = VALUE #( BASE lo_cut->mt_output_tbl ( pernr = mc_pernr_1 name = 'Mustermann' bukrs = 1000 kst = '826' datum = '20210101'
von = 'GLH' nach = 'GLH' kfz_kennzeichen = 'BBB' betrag = 2 ) ).
lo_cut->mt_output_tbl = VALUE #( BASE lo_cut->mt_output_tbl ( pernr = mc_pernr_2 name = 'Frauenhofer' bukrs = 1100 kst = '1225' datum = '20210105'
von = 'GLH' nach = 'WSH' kfz_kennzeichen = 'TEST-XB-88' betrag = 14 ) ).
lo_cut->mt_output_tbl = VALUE #( BASE lo_cut->mt_output_tbl ( pernr = mc_pernr_1 name = 'Mustermann' bukrs = 1000 kst = '826' datum = '20210104'
von = 'KT' nach = 'GLH' kfz_kennzeichen = 'BBB' betrag = 6 ) ).
lo_cut->mt_output_tbl = VALUE #( BASE lo_cut->mt_output_tbl ( pernr = mc_pernr_1 name = 'Mustermann' bukrs = 1000 kst = '826' datum = '20210105'
von = 'GLH' nach = 'WSH' kfz_kennzeichen = 'BBB' betrag = 9 ) ).
lo_cut->mt_output_tbl = VALUE #( BASE lo_cut->mt_output_tbl ( pernr = mc_pernr_2 name = 'Frauenhofer' bukrs = 1100 kst = '1225' datum = '20210105'
von = 'GLH' nach = 'WSH' kfz_kennzeichen = 'TEST-XB-88' betrag = '0.5' ) ).
Ich bekomme aber die 5 Einträge wie gewollt, ich nutze den BASE Operator doch innerhalb der VALUE Anweisungjocoder hat geschrieben: ↑22.02.2021 15:52Soll die Tabelle am Ende 5 Zeilen enthalten?
Der VALUE-Operator initialisiert die Tabelle immer zuerst. Am Schluss enthält sie daher nur eine Zeile.
So wäre es richtig:Code: Alles auswählen.
lo_cut->mt_output_tbl = VALUE #( BASE lo_cut->mt_output_tbl ( pernr = mc_pernr_1 name = 'Mustermann' bukrs = 1000 kst = '826' datum = '20210101' von = 'GLH' nach = 'GLH' kfz_kennzeichen = 'BBB' betrag = 2 ) BASE lo_cut->mt_output_tbl ( pernr = mc_pernr_2 name = 'Frauenhofer' bukrs = 1100 kst = '1225' datum = '20210105' von = 'GLH' nach = 'WSH' kfz_kennzeichen = 'TEST-XB-88' betrag = 14 ) BASE lo_cut->mt_output_tbl ( pernr = mc_pernr_1 name = 'Mustermann' bukrs = 1000 kst = '826' datum = '20210104' von = 'KT' nach = 'GLH' kfz_kennzeichen = 'BBB' betrag = 6 ) BASE lo_cut->mt_output_tbl ( pernr = mc_pernr_1 name = 'Mustermann' bukrs = 1000 kst = '826' datum = '20210105' von = 'GLH' nach = 'WSH' kfz_kennzeichen = 'BBB' betrag = 9 ) BASE lo_cut->mt_output_tbl ( pernr = mc_pernr_2 name = 'Frauenhofer' bukrs = 1100 kst = '1225' datum = '20210105' von = 'GLH' nach = 'WSH' kfz_kennzeichen = 'TEST-XB-88' betrag = '0.5' ) ).
Code: Alles auswählen.
READ TABLE mt_output_tbl INDEX 1 ASSIGNING FIELD-SYMBOL(<fs_prev_entry>).
Code: Alles auswählen.
CLEAR <fs_prev_entry>.
<fs_prev_entry> = <fs_entry>.
Code: Alles auswählen.
"Read 1st Line of Table for comparing
READ TABLE mt_output_tbl INDEX 1 ASSIGNING FIELD-SYMBOL(<fs_prev_entry>).
If sy-subrc <> 0.
RAISE EXCEPTION TYPE zcx_feh_exception.
ENDIF.
LOOP AT mt_output_tbl ASSIGNING FIELD-SYMBOL(<fs_entry>).
DATA(lv_tabix) = sy-tabix - 1.
IF sy-tabix = 1. "Skip first entry, its already assigned in <fs_prev_entry>
CONTINUE.
ENDIF.
"Same pernr means more than 1 entry for the same Person
" -> Add Betrag existing entry
IF <fs_prev_entry>-pernr = <fs_entry>-pernr.
<fs_prev_entry>-betrag = <fs_prev_entry>-betrag + <fs_entry>-betrag.
ELSE. "Next different Entry
MOVE-CORRESPONDING <fs_prev_entry> TO ms_privatfahrt.
INSERT ms_privatfahrt INTO TABLE check_sums.
**********************************************************************
* Do not execute this in Test CLass
**********************************************************************
* "Booking
* go_doc = NEW #( is_privatfahrten = ms_privatfahrt iv_akont = '11111111').
*
* TRY.
* go_doc->create_doc( ).
* CATCH cx_sy_duplicate_key
* zcx_feh_invalid_input " Ungültige Input Parameter
* INTO cx_root.
* MESSAGE cx_root->get_text( ) TYPE 'S' DISPLAY LIKE 'E'.
* ENDTRY.
**********************************************************************
READ TABLE mt_output_tbl ASSIGNING <fs_prev_entry>
INDEX lv_tabix.
ENDIF.
ENDLOOP.
Code: Alles auswählen.
METHOD booking_sort.
TRY.
lo_cut->book_doc( ).
CATCH zcx_feh_exception.
ENDTRY.
READ TABLE lo_cut->mt_output_tbl INDEX 1 ASSIGNING FIELD-SYMBOL(<fs_prev>).
If sy-subrc <> 0.
cl_abap_unit_assert=>fail( msg = 'Could not read First Line of Table mt_output_tbl').
ENDIF.
READ TABLE lo_cut->mt_output_tbl INDEX 1 ASSIGNING FIELD-SYMBOL(<fs_prev1>).
If sy-subrc <> 0.
cl_abap_unit_assert=>fail( msg = 'Could not read First Line of Table mt_output_tbl').
ENDIF.
If <fs_prev>-pernr <> mc_pernr_2.
cl_abap_unit_assert=>fail( msg = 'Wrong sorting Direction').
ENDIF.
LOOP AT lo_cut->mt_output_tbl ASSIGNING FIELD-SYMBOL(<fs_entry>).
IF sy-tabix = 1.
CONTINUE.
ENDIF.
IF sy-tabix = 2.
IF <fs_prev>-pernr <> <fs_entry>-pernr.
cl_abap_unit_assert=>fail( msg = 'Sorting was not executed correctly').
ENDIF.
ENDIF.
ENDLOOP.
ENDMETHOD.
Folgende Benutzer bedankten sich beim Autor jocoder für den Beitrag:
der_neuling