【发布时间】:2026-01-05 01:50:01
【问题描述】:
我有一个场景,我的类方法 (A) 调用另一个类方法 (B)。所以 A 依赖于 B。我想摆脱依赖以便能够运行单元测试。解耦和依赖注入在某种程度上是基于实例化的。但是类方法(静态方法)本质上不需要实例。 我已经制定了两个解决方案,但对我来说似乎没有一个是 100% 的:
- 我们创建 B 类实例(生产代码)或测试替身实例(用于单元测试)。我们将它作为参数注入到被测类方法中。在注入的实例上调用内部类方法,而不是在类上。
我不喜欢我们需要创建一个类的实例,尽管我们是 使用类方法。这可能需要时间。它需要更多代码。
- 我们将实际类名作为字符串参数注入,并使用动态
CALL METHOD。
由于我不喜欢解释型语言,我认为这是一团糟 会带来严重的运行时问题。由于我们这样做是为了实现单元 测试并因此消除可能的错误;使用动态调用似乎 适得其反。使用参数也很痛苦。
还有其他方法可以解决这个问题吗?有没有我遗漏的重要一点?
下面,这两种解决方案都有关键部分。理解问题并不重要,但它们可能会有所帮助。
1)
INTERFACE lif_readfile.
CLASS-METHODS gui_upload
IMPORTING file_path TYPE string
CHANGING data_tab TYPE truxs_t_text_data.
ENDINTERFACE.
CLASS lcl_file_operations DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
get_file_length
IMPORTING
!file_path TYPE string
CHANGING
!filereader TYPE REF TO lif_readfile OPTIONAL
RETURNING
VALUE(text_length) TYPE i.
ENDCLASS.
CLASS lcl_file_operations IMPLEMENTATION.
METHOD get_file_length.
*create instance of default productive class
IF filereader IS NOT BOUND.
filereader = NEW lcl_readfile( ).
ENDIF.
*use instance to call class method
filereader->gui_upload(
EXPORTING file_path = file_path
CHANGING data_tab = lt_data
).
*code under test here..
ENDMETHOD.
ENDCLASS.
2)
CLASS lcl_file_operations DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
get_file_length
IMPORTING
!file_path TYPE string
!classname TYPE string DEFAULT 'LCL_READFILE'
RETURNING
VALUE(text_length) TYPE i.
ENDCLASS.
CLASS lcl_file_operations IMPLEMENTATION.
METHOD get_file_length.
*parameter definition
ptab = VALUE #( ( name = 'FILE_PATH'
kind = cl_abap_objectdescr=>exporting
value = REF #( file_path ) )
( name = 'DATA_TAB'
kind = cl_abap_objectdescr=>changing
value = REF #( lt_data ) ) ).
DATA(meth) = 'LIF_READFILE~GUI_UPLOAD'.
*dynamic call
CALL METHOD (classname)=>(meth) PARAMETER-TABLE ptab.
*code under test here..
ENDMETHOD.
ENDCLASS.
【问题讨论】:
标签: unit-testing dependency-injection static-methods abap interpreted-language