Lesson 2 of 6
EML scenario tests: setup, COMMIT ENTITIES and teardown with ROLLBACK ENTITIES
11 min
Listen to this lesson
An EML scenario test drives the BO the way a consumer does: it creates or changes instances with MODIFY ENTITIES, runs actions, commits, and checks what was saved. SAP's RAP100 tutorial is the reference pattern, and Kenji's team copied its shape for ZCL_CMC_CORE_AGR_EML_TEST, a global test class in the agreement package. This lesson walks through it from the class definition to the last assertion.
The class skeleton
- Create a global class and add
FOR TESTING RISK LEVEL HARMLESS DURATION SHORTto the definition. The tutorial places it afterCREATE PUBLIC. - Add the ABAP Doc test relation as the first line:
"! @testing BDEF:ZR_CMC_CoreAgreement. Running ABAP Unit on the behavior definition now also runs this class; ADT lists it under Foreign Tests. - Declare class data for the environments: one of type
if_cds_test_environmentand one of typeif_osql_test_environment. - In
class_setup, create the CDS test environment for the BO's view entities withcl_cds_test_environment=>create_for_multiple_cds, and the SQL test environment withcl_osql_test_environment=>createfor other tables the behavior reads with ABAP SQL. - In
setup, callclear_doubleson both environments and insert the test data each test needs. - In
teardown, callROLLBACK ENTITIESso the next test starts with an empty transactional buffer. - In
class_teardown, calldestroyon both environments.
What the doubles redirect
The CDS test environment replaces the data sources of the view entities you name, so reads of ZR_CMC_CoreAgreement and the managed save land in doubles of ZCMC_CORE_AGR and ZCMC_CORE_AGI, not in the real tables. Tables the handlers read with ABAP SQL go into the SQL environment. Contoso's validateCustomer reads the released customer view, so Kenji's team inserts a row for Great Lakes Fleet Services, customer 17100001, into its double; the test then passes on any client, freshly refreshed or not. Check on your release which entities each factory method doubles; the dependency list is the first thing to look at when a test writes to a real table.
| Dependency | Environment | Test data in setup |
|---|---|---|
ZR_CMC_CoreAgreement and item view | CDS test environment | Usually none: the test creates agreements through EML |
| Released customer view read by validateCustomer | CDS test environment (added to the doubled entities) | 17100001 Great Lakes Fleet Services; a second fleet customer |
| Draft tables ZCMC_CORE_AGR_D and ZCMC_CORE_AGI_D | SQL test environment | None; draft tests create drafts through EML (lesson 4) |
| Any Z table read with ABAP SQL in a handler | SQL test environment | Only the rows that test needs |
Kenji's dependency list for the scenario test class: if a dependency is missing here, the test touches real data.
A scenario test, step by step
The test method create_agreement_and_commit proves the main path: create an agreement with two items, let the determinations work, commit, and read the saved state.
- Create.
MODIFY ENTITIES OF ZR_CMC_CoreAgreement ENTITY Agreement CREATE FIELDS ( Customer ValidFrom ValidTo ) WITH ...using%cid = 'AGR1', customer 17100001, valid for one year. - Create by association. In the same statement,
CREATE BY \_Itemwith%cid_ref = 'AGR1'adds two items for CMC-ALT-100 with deposits of 40.00 and 25.00 USD. - Collect responses.
MAPPED DATA(mapped) FAILED DATA(failed) REPORTED DATA(reported). Assertfailedis initial andmapped-agreementhas one entry. - Commit.
COMMIT ENTITIES RESPONSE OF ZR_CMC_CoreAgreement FAILED DATA(commit_failed) REPORTED DATA(commit_reported).Assertsy-subrcis 0 and both responses are initial. - Read back.
READ ENTITIESor aSELECTon the view. Assert Status is OPEN (setInitialStatus) and TotalDeposit is 65.00 (calcTotalDeposit). - Leave nothing behind. The doubles hold the saved rows; teardown rolls back the buffer and setup clears the doubles before the next test.
Negative scenarios
The same class holds the negative paths, each in its own method: reject_valid_to_before_from creates an agreement with ValidTo before ValidFrom, commits, and asserts sy-subrc 4, the key in commit_failed-agreement, and a message in commit_reported-agreement with %element-ValidTo marked. close_open_agreement creates and commits an agreement, executes closeAgreement, commits again and reads Status CLOSED. reject_zero_deposit expects the item validation to fail. Keep one behavior per method and name it after the behavior, not after the method being called.
- ArrangeAgreement for 17100001 with ValidFrom 2026-11-01 and ValidTo 2026-10-01
- ActMODIFY ENTITIES, then COMMIT ENTITIES RESPONSE OF the BO
- Assert subrcsy-subrc is 4: early save phase rejected the buffer
- Assert failedThe agreement's %cid or key appears in commit_failed
- Assert reportedMessage bound to ValidTo; check the message class and number, not the text
What goes wrong in testing
- Forgetting teardown. Without
ROLLBACK ENTITIES, a failed commit leaves instances in the buffer and the next test inherits them. Order-dependent results follow. - Asserting text. A test that compares the message text breaks when a translator improves the wording. Compare message class, number and the marked element.
- One test, five behaviors. A 200-line test that creates, closes, reopens and deletes fails without telling anyone which rule broke.
- Committing in the wrong place.
COMMIT ENTITIESis not allowed in behavior pools. It belongs in the test (the consumer), never in a handler.
What would you do?
Kenji's scenario test <code>reject_valid_to_before_from</code> passes on his machine but fails in the nightly run, where the agreement from a previous test is still in the buffer. What is the most likely fix?
- The RAP100 pattern: test relation to the BDEF, CDS and SQL doubles in class_setup, clear in setup, ROLLBACK ENTITIES in teardown.
- Assert after MODIFY ENTITIES and again after COMMIT ENTITIES, including sy-subrc.
- Negative tests check failed keys and the marked element of the message, not the message text.
- If a test writes to a real table, the dependency list is incomplete.
Check your understanding · not graded
Lesson check
1. What does the ABAP Doc comment "! @testing BDEF:ZR_CMC_CoreAgreement do?
2. Why does the scenario test class call ROLLBACK ENTITIES in teardown?
3. Where should the double for a table read with ABAP SQL in a handler be created?
4. A negative test should assert the message how?
5. Where may COMMIT ENTITIES be called?