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:

  1. 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.
  2. 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.

To report this post you need to login first.

12 Comments

You must be Logged on to comment or reply to a post.

  1. Glen Simpson

    Hi Uwe

    Thanks for your continued commitment to the improvement of MockA. I’m sure it is greatly appreciated by others in the community too.

    Would you mind confirming the impact of the first “breaking change” mentioned above with a more concrete example?

    Suppose I am writing local test classes for a productive class – I have 4 test classes, each class has 5 test methods and each test method requires 2 dependency classes to be mocked. In total, 40 mock objects will be created but many of the objects are based on the same dependency class so, in the MockA build we currently use in our system, the number of subroutine pools generated is much lower. If we now take the latest MockA build, will this result in the generation of 40 subroutine pools and therefore break the limit of 36?

    A second question… does the scenario change if all of the dependencies are mocked via class interfaces instead of via classes?

    Thanks again

    Glen

    (0) 
    1. Uwe Kunath Post author

      Dear Glen,

      In your case a subroutine pool is going to be created per each GENERATE_MOCKUP( ) call, given the fact that you specified a class in the MOCK( ) – method calls before.

      In case you create a mock object based on an interface, a subroutine pool is created only for the very first GENERATE_MOCKUP( ) – call for that interface.


      This means, you might indeed run into the subroutine-pool issue, if the 4 test classes reside in one test report.

      Please let me know if you figure out any issues.

      Your second question: yes, the scenario should change if you used interfaces, as mockA would create only two subroutine pools.

      Regards,

      Uwe

      (0) 
      1. Glen Simpson

        Thanks Uwe. That’s good news about mock objects based on interfaces being less affected than classes as we nearly always use interfaces. The example above could help avoid problems in the future if we’re forced to create mock objects for classes.

        (0) 
  2. Matthew Billingham

    I’ve got around the 36 subroutine pools limit by handing the work over to an RFC function module that starts a new task. I don’t know the details of mockA, but maybe you can use this workaround?

    (0) 
    1. Uwe Kunath Post author

      Dear Matthew,

      In mockA, the following static method serves as helper method for the local mock class report generation:

      METHOD generate_subroutine_pool.

         FREE: ev_prog,

               ev_subrc,

               ev_message.

         CATCH SYSTEM-EXCEPTIONS generate_subpool_dir_full = 9.

           GENERATE SUBROUTINE POOL it_code NAME ev_prog MESSAGE ev_message.

           IF sysubrc IS NOT INITIAL.

             ev_subrc = sysubrc.

           ENDIF.

         ENDCATCH.

         IF sysubrc = 9.

           ev_subrc = sysubrc.

           ev_message = text001.

         ENDIF.

      ENDMETHOD.


      Did you transfer such kind of coding to the RFC-call?


      Regards,


      Uwe

      (0) 
      1. Matthew Billingham

        What I needed was a very dynamic SQL call (that returns a number), that could only be done via subroutine generation. The first attempt was a method that gets the data with the GENERATE statement within it. That worked fine until the limit was reached.

        So I had:

        METHOD get_my_value importing i_some_critera returning a_value.

          ” generate form in subroutine pool according to i_some_criteria.

          ” perform the form in the generated code, determining a_value

        ENDMETHOD.

        I changed this to:

        METHOD get_my_value importing i_some_critera returning a_value.

          CALL FUNCTION ‘Z_GET_DATA’ DESTINATION ‘NONE’

            EXPORTING i_some_criteria

            IMPORTING a_value.

          CALL FUNCTION ‘RFC_CONNECTION_CLOSE’ exporting destination = ‘NONE’

        ENDMETHOD.

        and the function module contains

          ” generate form in subroutine pool according to i_some_criteria.

          ” perform the form in the generated code, determining a_value

        You need the RFC_CONNECTION_CLOSE otherwise the function module will run in the same context and you’ll hit the limit again!

        In the end, I changed my implementation to use STARTING NEW TASK, as I needed parallelisation anyway.

        Whether you can follow this technique depends, I guess, on how you’re using the generated subroutine pool.

        (0) 
        1. Glen Simpson

          Hi Matthew

          I hope Uwe doesn’t mind me answering this but hopefully he can correct me if I go off track.

          MockA uses subroutine pools to generate new (temporary) class definitions/implementations on which mock objects can be created and then used in a test program. The new class must be available within the context of the test program otherwise the creation of the mock object will fail (because he new class type will be unknown). I haven’t tested this to confirm it but I think that if the subroutine pool is generated in a new task then the new class will not be available to the test program…?

          Regards

          Glen

          (0) 
          1. Uwe Kunath Post author

            Dear Glen, I strongly believe you are right – as of my understanding the temporary local class implementation will need to be created in the same context as the unit test report.

            Regards, Uwe

            (0) 
  3. Suhas Saha

    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.

    Hi Uwe,

    It is not possible to mock a private element of a non-final class even if mockA is defined as a FRIEND? Can this behaviour be supported by mockA?

    BR,

    Suhas

    (0) 
    1. Uwe Kunath Post author

      Dear Suhas,

      unfortunately, this won’t work, as you would have to make the locally generated mock class a friend of your class – making the mockA core class a friend won’t be enough.

      Theoretically, we could think of a feature which would allow us to generically access private attributes via the mockA core class – and allow access to the generic setter methods in the local mock class. However, there is no such functionality yet.

      Nevertheless,
      You should consider to declare your private attributes protected instead, which would be enough for mockA to work.

      Regards,

      Uwe

      (0) 
      1. Suhas Saha

        Hello Uwe,

        You should consider to declare your private attributes protected instead, which would be enough for mockA to work.

        That’s the workaround i’ve been using 🙂

        Theoretically, we could think of a feature which would allow us to generically access private attributes via the mockA core class – and allow access to the generic setter methods in the local mock class. However, there is no such functionality yet.

        Sounds good to me. Maybe you can add this to your backlog for the next release of mockA 😎

        Have a nice day.

        BR,

        Suhas

        (0) 

Leave a Reply