Technical Articles
Test Doubles are coming to Function Modules
More of an announcement rather than a blog: Drumroll for the latest in Unit Testing Frameworks, Function Modules.
Function modules have always been the thorn in the side of anyone trying to write ABAP Unit Tests. The only sensible way to mock a call to a function module was to wrap the FM into a class method and then mock that, either via the OO Test Double Framework or by coding explicit test doubles.
Well, the next shiny new version of ABAP (7.56) includes a Function Module test double. And while I could write a nice blog with examples, SAP have stolen my thunder and done a sterling job of documenting it in good detail with great examples over here. Personally I really like the simple, easy to understand way the framework is structured.
For those on 7.56, enjoy! The rest of us will have to be very patient. But at least for those on lower versions it’s always handy to know what’s coming in order to avoid spending too much resources on reinventing a future wheel.
Have Fun!
Update: Following a great hint from Thomas Fiedler that this is available in the ABAP Cloud trial system, I managed to give it a little go. I used a simple method that calls BAPI_MESSAGE_GETDETAIL and returns the message text.
method get_message.
data: message type bapiret2-message,
return type bapiret2.
call function 'BAPI_MESSAGE_GETDETAIL'
exporting
id = '00'
number = 000
textformat = 'HTM'
importing
message = message
return = return.
result = message.
endmethod.
A quirk I discovered was that, mocking a call where I don’t care about the input to the FM proved to be more complex than setting up a scenario with expected input parameters. One needs to implement interface if_ftd_invocation_answer
instead of just calling create_input_configuration
.
For convenience and brevity I implemented the interface in the test class so I could control everything in one class and pass me
as the answering object, thus:
class ltc_test definition final for testing
duration short
risk level harmless.
public section.
interfaces if_ftd_invocation_answer.
private section.
constants mock_text type string value `The moon is made of green cheese`.
methods fm_is_mocked for testing raising cx_static_check.
endclass.
class ltc_test implementation.
method fm_is_mocked.
data(function_double) = cl_function_test_environment=>create(
value #( ( 'BAPI_MESSAGE_GETDETAIL' ) ) )->get_double( 'BAPI_MESSAGE_GETDETAIL' ).
function_double->configure_call( )->ignore_all_parameters( )->then_answer( me ).
cl_abap_unit_assert=>assert_equals( act = new zcl_message( )->get_message( )
exp = mock_text ).
endmethod.
method if_ftd_invocation_answer~answer.
result->get_output_configuration( )->set_exporting_parameter( name = 'MESSAGE'
value = mock_text ).
endmethod.
endclass.
Wanting to write unit tests on a lower release, though, was a great learning experience: I had to design an interface to abstract DB operations and feed test data via helper methods.
Sadly, only a small group of developers (and companies) actually care about tests during development.
Thanks for your comments. Agree testing and code quality in general still seems to be undervalued in many projects.
I had the same learning experience, and is not just about unit tests, but how they help you to write better code.
+1.
Not only do they provide the so-called "safety net" against regression, but they also make your code cleaner and more structured.
To make it clear to everyone, from the link you posted: "ABAP function module test double framework is available since back-end version SAP NetWeaver AS for ABAP 7.56."
Thanks Sandra, I did mention it in the last paragraph, but have added the version number to the main text to be clear.
Is 7.6 same as 7.56?
Argh! Yes of course, I meant 7.56. Corrected, thanks!
I have been using it for sometime now. IMO, the mocking technique used in FTDF (SET...WHEN...THEN) is more polished than that of the ATDF.
Agree, I always did find he class framework a bit clunky and this one is much nicer for the reader too.
You can play around with the new framework on the Steampunk Trial.
Regards,Thomas.
Great hint, thanks! Played, success, updated blog.
Hi Mike,
You can also configure the output, also when you ignore all the input parameters. I don't think that you need to implement the interface IF_FTD_INVOCATION_ANSWER explicitly.
Hi Suhas,
Understood, but you are using the
then_set_output
method. From the method names I would infer a simpler syntax usingthen_answer
, something like:Or an even shorter nice to have:
Either of these would be more compact and easier to understand, and would cover many of my use cases.
Hello Mike.
Thank you very much for this useful blog.
Please let me confirm one thing.
Function modules can be doubled by this way are only the ones that are not using the DESTINATION (RFC destination) parameter.
I could double the function BAPI_USER_EXISTENCE_CHECK that is not using the DESTINATION parameter, but I could not double it when that function module is using the DESTINATION.
That's why now I am asking this question.
I could not find any specifications about this behavior in any official documents (e.g. the following site), so now I am here to ask.
https://help.sap.com/docs/ABAP_PLATFORM_NEW/c238d694b825421f940829321ffa326a/75964f284aa9435da40c4d82e111f276.html?&version=202110.000
If you have any information about this topic, please let me know.
Thank you very much for your support in advance.
Regards
Takahiro.