Menu

Software architecture with SAP

I recently had the chance to have a look into SAP’s ABAP Test Double Framework. Previously, the main tool for mock object creation was mockA, which did a great job in my previous projects.

Code readability

The Test Double Framework’s fake object creation is quite straight forward. Creating such an instance is handy and even allows you to use the native method call to specify the importing-parameters. Please see the blog post from SAP:

As you can see, mockA doesn’t allow to verify whether you correctly supplied the method’s importing-parameters and method name at design time. This restriction applies for the Test Double Framework only for exporting and changing-parameters.
The only two disadvantages that I’ve recognized are

checked exceptions need to be catched in a dummy TRY…CATCH…RETURN…ENDTRY-statement to avoid ATC messages

the exporting- and returning parameters specification comes before the actual method call specification and configuration of the importing parameter. You need to get used to it, but it’s fine

Let the framework ignore importing parameters

The Test Double Framework allows you to separately ignore importing parameters by attaching “->ignore_parameter(…)” to your “configure_call(…)” method call. This feature is not yet existent in mockA. However, if you avoid the “->with(…)” method call in mockA completely, it will return the specified output in any case . This is equivalent to “->ignore_all_parameters(…)”.

Custom matchers

The Test Double Framework allows you to pass custom matchers which will implement interaction verifications on the fake method input parameters. The interface is called if_abap_testdouble_matcher and it is very easy to implement. mockA does not offer such a concept.

System requirements

mockA requires NW 7.01. The Test Double Framework requires NW 7.40.

Object support

mockA supports classes and interfaces, while the Test Double Framework supports interfaces, but no classes at the moment.

Conclusion

The Test Double Framework is a really nice mocking framework. It works very well and offers functionality, which mockA doesn’t offer. However, some drawbacks still exist, e.g. when you want to mock classes or work with NW releases lower than 7.40

The current release of mockA is available at Github. It contains an error fix that I would like to outline in today´s blog post.

The bug

MockA allows you to mock classes as described in one of my previous blog posts. Technically, mockA tries to create a subclass of the class which is subject to the mock creation. This means, it will only work, if the class is not marked as final and has a constructor which is at least protected or public.

MockA overrides methods that should be mocked, with a local implementation that returns the values expected to be returned. It follows the specifications set up by the unit test, according to the method( ), with( ) and exports( ) or returns( ) -calls (and so on) during mock creation.

There is another feature that reuses generated subroutine pools that have been created by mockA, because the Web Application Server ABAP allows only about 36 subroutine pools for each program, or, in our case, per unit test. The generated code does not contain any hard coded method output parameters as there would be no benefit in buffering the generated coding then. Instead, the instance of type ZIF_MOCKA_MOCKER is passed to the mock object. In the mock object´s method implementations, the fake values are read from that instance. If a new mock object should be created, a new instance of ZIF_MOCKA_MOCKER will be passed to the mock object. Hence, the method output may change.

If mockA generates the local implementation of an interface, each method is implemented during the initial mock class generation, so this feature poses no issues here.

However, in case a class needs to be mocked, mockA also tried to reuse these generated subroutine pools in the past. Do you see the error?

What could possibly happen

Imagine, mockA should create a mock implementation of the following class: ZCL_I_CAUSE_TROUBLE which has two methods:

METHOD_A

METHOD_B

In our first unit test, we will tell mockA to simulate the output of METHOD_A, without defining any output for METHOD_B.

When the mock object is created, mockA will generate a local subclass of ZCL_I_WILL_CAUSE_TROUBLE, with a local implementation of method METHOD_A that overrides the parent´s class method. The parent´s class method cannot be called any longer via the mock object. METHOD_B_ remains untouched.

After generation of the subroutine pool, the class implementation is buffered for later usage.

If another unit test, that is executed after the first one, wants to control the output of METHOD_B, mockA won´t return that output, as the method has not been overridden in the first unit test and therefore no output control takes place in the locally created class implementation: The logic that is responsible for returning the specified fake values is simply not called. Instead, the super implementation of ZCL_I_WILL_CAUSE_TROUBLE is called.

The solution

Subroutine pool buffering is now generally switched off if a class needs to be simulated. For interfaces, the current logic remains unchanged.

Unfortunately, this change is a breaking change, which can lead to failing unit tests, which have passed in the past.

This change could cause some new issues that I would like to outline briefly:

Subroutine pool limits might be violated for existing unit tests. As there might be multiple implementations generated per class within the same unit test report, the subroutine pool limit might be violated once you updated mockA. In this case, please split up your test methods into various reports, if possible.

Please see the example above: If your second unit test tells mockA to simulate the output of METHOD_B, but actually expects a result that is returned by the super implementation, your unit test might fail now, as the super implementation is not called any longer due to the correction and instead, the specified fake values will be returned.
I know that this is just a theoretical consideration but important to be mentioned. Nevertheless, these test cases can be considered incorrectly implemented, as the unit test possibly expects other values than the values that have been defined as output for METHOD_B. Hence, these test cases should be reviewed anyway!

Feedback welcomed

There is no possibility to switch off the currently implemented behaviour of mockA as I think it is more important to fix the error than to allow old and incorrect unit test implementations not to fail.

Please let me know, if you run into trouble with the new update, and if issue 1) or 2) applies, or maybe both. Please also tell me, if you figured out another issue that I didn´t think of now.

Introduction

This blog post is strongly connected to the presentation that has been given by Damir Majer and Martin Steinberg during SAP Inside Track 2014 in Munich.

The presentation focuses on solving a code kata using Test-Driven Development (TDD).

The purpose is to show how TDD can lead to better tests coverage, thus more robust and maintainable software components. This blog post focuses not about the solution of the code kata itself, but rather on how to test each component separately from each other using mockA.

The Kata

Summarized, the Kata says:

Implement a simple String calculator class that accepts a flexible amount of numbers in a string. The numbers should be summed up and the sum needs to be returned.

Examples:

An empty string returns “0”

For single numbers, the number itself will be returned, e.g. for “1”, the sum 1 will be returned

For “1,2”, the sum 3 will be returned

Also multiple delimiters will have to be accepted, e.g. “1;2\3;1” will lead to 7

Ensure, that the output of compute is returned without modification (result will be 10)

Such a test will need you to subclass ZCL_STRING_CALCULATOR and redefine the helper methods with hard coded return values based on specific inputs. Furthermore, some logic behind “compute” should allow you verify if the method has been called with the correct parameters.

Subject to the test will be the subclass of ZCL_STRING_CALCULATOR, which will partly contain so called faked functionality regarding “replace_delimiter_with_comma”. But it will also contain some mock features, as “compute” should not only conditionally return some values based on its input, but it should also allow you to determine, if it has been called with the expected input.

mockA allows you to skip this subclassing and lets you focus on the test. It will create a subclass at runtime for you, which follows constraints like conditional method output. These constraints can be hard coded by you. It will also allow you to verify method calls of mocked methods.

“Unit Test v2.txt” shows you how to do it. Keep a look a test method “test_add”.

What has been missing so far

In one of my last blog posts, I showed you how mock objects can be easily created. I also showed you how mock object’s method calls can be counted and how verifications can be implemented, to ensure that a mocked object’s method has been called.
Up to now, it was not possible to check, which parameters have been passed.

Ensure, that a mocked object has been called with certain parameters

In the current build, I also included the possibility to verify the parameters that have been passed to a mock object’s method.
This is how it works:
First of all, you need to keep track of the mocker object of type ZIF_MOCKA_MOCKER (which means, please do not throw it away 😉 )
By utilizing this mocker object, you can get data about your mocked methods, such as if it has been called with certain parameters or not:

With mockA it is quite easy to mock interfaces for unit tests. But it is also capable of creating mock objects that are not based only on interfaces, but specific classes. This blog post shows how it works and what needs to be considered.

Basics

Creating such an instance is quite the same as the creation of mock objects based on interfaces. The only restriction that applies is the fact that the class which is to be mocked may not be final class. This is necessary because mockA couldn’t create a subclass to override method outputs.

The classes in the following examples can be found in the mockA package provided at Github.

Constructor parameters

However, this little example will still fail, as ZCL_MOCKA_FLIGHT_OBSERVER’s constructor expects non-optional IMPORTING parameters. This is an issue which is not existent for interfaces. As you mock already existing implementations, you also need to take care of that.

But that is also no problem at all. Consider the following example that passes some earlier created instances to the constructor. It can be achieved by calling the method PASS_TO_SUPER_CONSTRUCTOR of the mocker instance.DATA lo_is_in_time_info TYPE REF TO zif_mocka_is_in_time_info.
DATA lo_flight_alert_process TYPE REF TO zif_mocka_flight_alert_process.
*create lo_is_in_time_info and lo_flight_alert_process... (not shown here)
DATA lo_mocker TYPE REF TO zif_mocka_mocker.
DATA lo_mocker_method TYPE REF TO zif_mocka_mocker_method.
DATA lo_flight_observer TYPE REF TO zcl_mocka_flight_observer.
lo_mocker = zcl_mocka_mocker=>zif_mocka_mocker~mock( zcl_mocka_flight_observer=>gc_name ).

The example s are also in the mockA package. Take a look at the unit test report ZTEST_CL_MOCKA_MOCKER and the test methods mock_class_with_construc_param, mock_class_with_method_output and mock_intf_with_construc_param.