在 ABAP 单元测试中模拟 sy-uname



我正在尝试用ABAP编写我的第一个单元测试。

我测试的方法获取登录用户的团队成员(通过系统变量sy-uname(。

由于我希望测试为每个人运行,因此我不能只是让该方法运行并断言我自己的团队成员之一。

我想模拟sy-uname,所以测试不依赖于谁在执行它。

这可能吗?如果是,您如何模拟系统参数?

我半同意 Haojie 给出的答案:对于如此简单的情况(替换sy-uname(,不应该使用 Test Seams(自 ABAP 7.50 以来存在(,您应该只使用他建议的提供程序类。

测试接缝被认为是对生产代码的污染,因为它降低了代码的可读性(生产代码和测试代码的混合(。

注意:测试接缝的ABAP文档(上面的链接(至少给出了以下可能的用法:

  • 授权检查(权限检查(
  • ABAP SQL语句(SELECT,MODIFY等( - 它成为一个不好的例子,因为ABAP SQL可以用ABAP 7.52类CL_OSQL_TEST_ENVIRONMENT来模拟。

根据经验,根本不应使用测试接缝,也不应将其视为最后的解决方案。

但是,如果没有其他选择,比如将测试添加到"遗留"代码中(编写得很糟糕的旧代码,通常不使用面向对象的设计模式编写,被认为无法通过ABAP Unit进行测试(,那么您最终可能别无选择。

正如Horst Keller(世界上最好的ABAP专家之一,负责SAP的ABAP文档(所说:

"如果你不能重新设计和重写整个应用程序,作为一种解决方法,你使代码测试依赖于。这被认为是不好的风格,但它有帮助。

由于问题只是关于sy-uname而不是关于整个程序,所以重构sy-uname的努力要少得多,所以没有理由不使用类。

据我所知,不可能模拟系统参数。 有两种方法可以实现此目的。

1.试缝/试注塑

TEST-SEAM sy_uname.
DATA(lv_uname) = sy-uname.
END-TEST-SEAM.  
"other code 

您的单元测试:

TEST-INJECTION y_uname.
lv_name = "my_mock_user".
END-TEST-INJECTION.

2.测试双

定义接口

INTERFACE if_user
METHODS get_uname
RETURNING 
VALUE(rv_uname) TYYPE syst_uname.
ENDINTERFACE.

在生产代码中,创建一个 CLASS 来实现此接口,并且 在返回sy-unameget_uname.

在代码中的某个地方,您需要提供一个 SET 方法,以便能够设置如下所示的IF_USER实例,在生产代码中,您调用if_user~get_uname的实例以获取用户名。

METHODS set_user_provider
IMPORTING 
!io_user_provider TYPE REF TO if_user.

在单元测试代码中,创建一个本地 CLASS 来实现此接口和 在get_uname返回您的模拟用户。

CLASS lcl_mock_user_provider DEFINITION FOR TESTING. 
PUBLIC SECTION.
INTERFACES if_user.
ENDCLASS. 
CLASS lcl_mock_user_provider IMPLEMENTATION.
METHOD if_user~get_uname.
"return your mock user name. 
ENDMETHOD. 
ENDCLASS.

您的单元测试代码:

DATA(lo_mock_user_provider) = NEW lcl_mock_user_provider( ).
MyClassInstance.set_user_provider( lo_mock_user_provider ). 

关于只替换一个系统变量,我会去测试接缝。

通过接口封装系统变量,需要调用方实例化类,可能将实例作为参数传递给多个方法。这会导致复杂性增加和性能下降。如果存在需要系统变量以外的其他值的方案,则这可能是合理的。

测试接缝会降低生产代码的可读性,因此可能被视为对源代码的污染。然而,人们需要考虑是否需要额外的参数,甚至不会引入更多的噪声。

相关内容

  • 没有找到相关文章

最新更新