‎2024 Aug 15 10:05 AM - edited ‎2024 Aug 15 10:07 AM
I have been tryin to UNIT test a Method in a BDEF Implementation class.
Tutorials reviewed include:
https://developers.sap.com/tutorials/abap-environment-rap100-unit-testing..html
https://community.sap.com/t5/technology-blogs-by-sap/abap-units-in-abap-restful-programming-model/ba...
https://help.sap.com/docs/ABAP_PLATFORM_NEW/fc4c71aa50014fd1b43721701471913d/6477e7b5f4594498973ce5c...
Ive looked at similar code in /dmo/bp_travel_m Test classes and similar examples on github.
I have been trying for many hours to get unit testing working on a generated BDEF implementation class.
And I cant get the READ ENTITIES to use Mock data from a unit test.
Background:
I started with a simple table with a generated Business Configuration.
Similar to this https://developers.sap.com/tutorials/abap-environment-business-configuration-object..html
My configuration maintenance object and it UI is working.
The BDEF that was generated has an extension.
custom validation extras are common. See posts like
https://community.sap.com/t5/technology-blogs-by-members/how-to-perform-field-validation-in-abap-res...
The BDEF, and what I added:
validation CheckIntfNameAndClassName on save { create; update; } <<<<ADDED
draft determine action Prepare {
validation FactoryOverride ~ ValidateDataConsistency;
validation CheckIntfNameAndClassName; <<<< ADDED
}
He is the FULL BDEF
managed with additional save implementation in class /OXO/BP_I_FACTORYCUSTOV_S unique;
strict;
with draft;
define behavior for /OXO/I_FactoryCustOv_S alias FactoryCustOvAll
draft table /OXO/D_FACTORY_S
with unmanaged save
lock master total etag LastChangedAtMax
authorization master( global )
{
field ( readonly )
SingletonID,
TransportRequestID;
field ( notrigger )
SingletonID,
HideTransport,
LastChangedAtMax;
update;
internal create;
internal delete;
draft action ( features : instance ) Edit;
draft action Activate optimized;
draft action Discard;
draft action Resume;
validation CheckIntfNameAndClassName on save { create; update; }
draft determine action Prepare {
validation FactoryOverride ~ ValidateDataConsistency;
validation CheckIntfNameAndClassName;
}
action ( features : instance ) SelectCustomizingTransptReq parameter D_SelectCustomizingTransptReqP result [1] $self;
association _FactoryOverride { create ( features : instance ); with draft; }
}
define behavior for /OXO/I_FactoryOverride alias FactoryOverride
persistent table /OXO/FACTORYCUST
draft table /OXO/D_FACTORYCU
etag master LocalLastChangedAt
lock dependent by _FactoryCustOvAll
authorization dependent by _FactoryCustOvAll
{
field ( mandatory : create )
IntfName;
field ( readonly )
SingletonID,
CreatedBy,
CreatedAt,
LastChangedBy,
LastChangedAt,
LocalLastChangedBy,
LocalLastChangedAt;
field ( readonly : update )
BusinessContext,
IntfName;
field ( notrigger )
SingletonID,
CreatedBy,
CreatedAt,
LastChangedBy,
LastChangedAt,
LocalLastChangedBy,
LocalLastChangedAt;
update( features : global );
delete( features : global );
mapping for /OXO/FACTORYCUST
{
BusinessContext = BUSINESS_CONTEXT;
IntfName = INTF_NAME;
UseSingleton = USE_SINGLETON;
ClassName = CLASS_NAME;
CreatedBy = CREATED_BY;
CreatedAt = CREATED_AT;
LastChangedBy = LAST_CHANGED_BY;
LastChangedAt = LAST_CHANGED_AT;
LocalLastChangedBy = LOCAL_LAST_CHANGED_BY;
LocalLastChangedAt = LOCAL_LAST_CHANGED_AT;
}
association _FactoryCustOvAll { with draft; }
validation ValidateTransportRequest on save ##NOT_ASSIGNED_TO_DETACT { create; update; delete; }
validation ValidateDataConsistency on save { create; update; }
}
It generates a STUB Method the Class method in the class supporting the BDEF.
CheckIntfNameAndClassName FOR VALIDATE ON SAVE
IMPORTING keys FOR FactoryCustOvAll~CheckIntfNameAndClassName.
I implemented my check. The check works as expected. I looked as similar methods when
implementing the method. But I must I do not fully understand the READ ENTITIES code.
But the Validation Method is working exactly as i expect it to.
It checks the DRAFT before allowing it to be saved.
METHOD CheckIntfNameAndClassName.
" Access the FactoryOverride composition (draft data )
READ ENTITIES OF /OXO/I_FactoryCustOv_S IN LOCAL MODE
ENTITY FactoryCustOvAll BY \_FactoryOverride
" with SingletonID = 1, and draft data see generated CDS
ALL FIELDS WITH VALUE #( ( SingletonID = 1
%is_draft = if_abap_behv=>mk-on ) )
RESULT DATA(lt_factory_override)
FAILED DATA(ls_failed_child)
REPORTED DATA(ls_reported_child).
LOOP AT lt_factory_override ASSIGNING FIELD-SYMBOL(<ls_factory_override>).
" The CHECK IS HERE
data(L_Ok) = SOME_CHECK(
intf_name = <ls_factory_override>-IntfName
class_name = <ls_factory_override>-ClassName ).
if l_ok = abap_true.
continue.
endif.
APPEND VALUE #( %tky = <ls_factory_override>-%tky )
TO failed-factoryoverride.
APPEND VALUE #( %tky = <ls_factory_override>-%tky
%msg = new_message( id = '/OXO/CORE_MSG'
number = '001'
v1 = <ls_factory_override>-IntfName
v2 = <ls_factory_override>-ClassName
severity = if_abap_behv_message=>severity-error )
%element-IntfName = if_abap_behv=>mk-on )
TO reported-factoryoverride.
ENDLOOP.
ENDMETHOD.
CLASS /oxo/bp_i_factorycustov_s DEFINITION LOCAL FRIENDS ltcl.
CLASS ltcl DEFINITION FINAL FOR TESTING
DURATION SHORT
RISK LEVEL HARMLESS.
PRIVATE SECTION.
CLASS-DATA:
cds_test_environment TYPE REF TO if_cds_test_environment,
sql_test_environment TYPE REF TO if_osql_test_environment,
class_under_test TYPE REF TO lhc_/OXO/I_FACTORYCUSTOV_S.
CLASS-METHODS:
class_setup,
class_teardown.
METHODS:
setup,
teardown,
test_valid_combi_cds_test FOR TESTING RAISING cx_static_check,
test_valid_combi_entities FOR TESTING RAISING cx_static_check.
ENDCLASS.
CLASS ltcl IMPLEMENTATION.
METHOD class_setup.
cds_test_environment = cl_cds_test_environment=>create_for_multiple_cds(
i_for_entities = VALUE #( ( i_for_entity = '/OXO/I_FACTORYCUSTOV_S' ) )
).
" OBSERVATION cds_test_environment internally only has double for
" /oxo/factorycust and not teh draft tables . So how can you set them ???
cds_test_environment->enable_double_redirection( ).
sql_test_environment = cl_osql_test_environment=>create(
i_dependency_list = VALUE #( ( '/OXO/D_FACTORYCU' )
( '/OXO/D_FACTORY_S' )
)
).
CREATE OBJECT class_under_test FOR TESTING.
ENDMETHOD.
METHOD class_teardown.
cds_test_environment->destroy( ).
sql_test_environment->destroy( ).
ENDMETHOD.
METHOD setup.
cds_test_environment->clear_doubles( ).
sql_test_environment->clear_doubles( ).
ENDMETHOD.
METHOD teardown.
ROLLBACK ENTITIES.
ENDMETHOD.
METHOD test_valid_combi_cds_test.
" I cant get the CDS_TEST_ENVIRONMENT to work.
" only /oxo/factorycust is generated as double.
" the read entities never finds any data.
DATA: lt_factorycust TYPE STANDARD TABLE OF /oxo/factorycust.
lt_factorycust = VALUE #( (
Intf_Name = '/OXO/IF_VALID'
Class_Name = '/OXO/CL_VALID' ) ).
cds_test_environment->insert_test_data( lt_factorycust ).
" ive tried adding the missing cds data via sql_test_environment
" this doesnt help.... The read entities in the Method under test is always empty.
DATA: lt_d_factory_s TYPE STANDARD TABLE OF /oxo/d_factory_s.
lt_d_factory_s = VALUE #(
( SingletonID = 1
hasActiveEntity = abap_false " This indicates it's a draft?
) ).
sql_test_environment->insert_test_data( lt_d_factory_s ).
" Prepare test data for FactoryOverride
DATA: lt_d_factorycu TYPE STANDARD TABLE OF /oxo/d_factorycu.
lt_d_factorycu = VALUE #(
( SingletonID = 1
BusinessContext = ''
IntfName = '/OXO/IF_VALID'
ClassName = '/OXO/CL_VALID'
UseSingleton = abap_false
hasActiveEntity = abap_false " ?? is this right ??
) ).
sql_test_environment->insert_test_data( lt_d_factorycu ).
DATA: failed TYPE RESPONSE FOR FAILED LATE /OXO/I_FactoryCustOv_S,
reported TYPE RESPONSE FOR REPORTED LATE /OXO/I_FactoryCustOv_S.
class_under_test->CheckIntfNameAndClassName(
EXPORTING
keys = VALUE #( ( SingletonID = 1 %is_draft = if_abap_behv=>mk-on ) )
CHANGING
failed = failed
reported = reported
).
" Verify the results
cl_abap_unit_assert=>assert_initial( failed ).
cl_abap_unit_assert=>assert_initial( reported ).
ENDMETHOD.
METHOD test_valid_combi_entities.
" I CANT GET THIS TO WORK, is this even the right way ?????
" It always returns FAILED (ls_failed)
" so what is the correct syntax to modify the entities ?????
MODIFY ENTITIES OF /OXO/I_FactoryCustOv_S
ENTITY FactoryCustOvAll
CREATE SET FIELDS WITH VALUE #(
( %cid = 'ROOT1'
%is_draft = if_abap_behv=>mk-on
"SingletonID = 1 " is read only how to pass this in, if it doesnt auto set ?
)
)
CREATE BY \_FactoryOverride
FIELDS ( BusinessContext IntfName ClassName UseSingleton )
WITH VALUE #(
( %cid_ref = 'ROOT1'
%target = VALUE #(
( %cid = 'CHILD1'
BusinessContext = 'TEST_CONTEXT'
IntfName = '/OXO/IF_VALID'
ClassName = '/OXO/CL_VALID'
UseSingleton = abap_false )
)
)
)
MAPPED DATA(ls_mapped)
FAILED DATA(ls_failed) " fail is set. Cause "not_found"
REPORTED DATA(ls_reported).
"not point continuing here as MOFIFY ENTITIES always fails......
" Verify that the test data was created successfully
* cl_abap_unit_assert=>assert_initial( ls_failed ).
* cl_abap_unit_assert=>assert_initial( ls_reported ).
*
* " Execute the method under test
* DATA: failed TYPE RESPONSE FOR FAILED LATE /OXO/I_FactoryCustOv_S,
* reported TYPE RESPONSE FOR REPORTED LATE /OXO/I_FactoryCustOv_S.
*
* class_under_test->CheckIntfNameAndClassName(
* EXPORTING
* keys = VALUE #( ( SingletonID = 1 %is_draft = if_abap_behv=>mk-on ) )
* CHANGING
* failed = failed
* reported = reported
* ).
*
* " Verify the results
* cl_abap_unit_assert=>assert_initial( failed-factoryoverride ).
* cl_abap_unit_assert=>assert_initial( reported-factoryoverride ).
ENDMETHOD.
ENDCLASS.
So how can you unit test
class_under_test->CheckIntfNameAndClassName
All attempts to mock data for the method under test call dont work.
I attached the generated view entities and the 3 tables.
The 2 draft tables are also generated.
Request clarification before answering.
| User | Count |
|---|---|
| 9 | |
| 6 | |
| 4 | |
| 4 | |
| 3 | |
| 3 | |
| 2 | |
| 2 | |
| 2 | |
| 2 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.