An important principle for unit testing is to separate data access from business logic. One efficient technique for this is to define interfaces for data access. Your main class always use a reference to that interface instead of direct reading or writing data.
in production code the main class will be given an object that wraps actual data access. This could be select statement, function mudule calls, anything really. The important part is that this class should not perform anything else. No logic.
When testing the main class, you give it an object that serves static, fake data instead.
An example for accessing the
Data access interface
INTERFACE zif_db_scarr PUBLIC. METHODS get_all RETURNING VALUE(rt_scarr) TYPE scarr_tab . ENDINTERFACE.
Fake data class and test class:
CLASS lcl_db_scarr DEFINITION. PUBLIC SECTION. INTERFACES: zif_db_scarr. ENDCLASS. CLASS lcl_db_scarr IMPLEMENTATION. METHOD zif_db_scarr~get_all. " generate static data here ENDMETHOD. ENDCLASS. CLASS lcl_test DEFINITION FOR TESTING DURATION SHORT RISK LEVEL HARMLESS. PRIVATE SECTION. DATA: mo_cut TYPE REF TO zcl_main_class. METHODS: setup. ENDCLASS. CLASS lcl_test IMPLEMENTATION. METHOD setup. DATA: lo_db_scarr TYPE REF TO lcl_db_scarr. CREATE OBJECT lo_db_scarr. CREATE OBJECT mo_cut EXPORTING io_db_scarr = lo_db_scarr. ENDMETHOD. ENDCLASS.
The idea here is that in production code,
ZCL_MAIN_CLASS will get a
ZIF_DB_SCARR object that does a
SELECT and returns the whole table while the unit test runs against a static dataset defined right there in the unit test include.