Claiming ABAPUnit – Again. Part 3: I slowly get why interfaces are good and how mocking works.
If you follow my activities, you know that I am getting into ABAP Unit, and sometimes I share my learnings and questions.
Those are some recent posts:
So, I kind of know for a long time that one should “program against an interface, not a class”, but I never really did.
But recently I started to extract interfaces and see how working with them is.
Now I can share a benefit I experienced:
Of course my parameter class has no public methods to set or clear a parameter. And also, it should not have that (parameters a read from customizing tables).
But my mock parameter class I define in the unit test, can very well have such methods (and I can create another one, whenever needed).
And as the both implement the interface, I can use any of them.
[This is probably a textbook example, so it might be not much news to you – but for me, experiencing this in my own, real work is so much more impressive than reading or hearing about the theoretical concept. I think it really clicked]
In an effort of “don’t repeat yourself” I tried putting what I want to tell about my test in comments. So the core of this blog post is this code block:
*There is a check, that the stock passed in has to have certain characteristics, *e.g. a stock type (cat), that is defined as "available". *The definition which stock types are "available" (e.g. F1, F2) is done in customizing-tables *and read by and stored in the parameter object (zifewm_mon_stock_mover_params ), that is passed into *the stock_mover (code under test = cut). METHOD is_not_available_stock_cat. "[given:] mt_mock_data = VALUE #( ( cat = 'B6' ) ). "Data, simulating a line in /SCWM/MON: it has a certain value for stock type. (all other fields don't matter) mref_mock_prameters->clear_stock_cat_available( ). "Make sure that stock type is not in the list of acceptable stock types. "create the stock mover, passing in the mock data and the mock parameters object. cut = NEW zclewm_mon_stock_mover( it_data = mt_mock_data iref_parameters = mref_mock_prameters ). "[when:] *we can now call the public method that contains the check. TRY. cut->check_and_move_stock( ). CATCH zclewm_cx_input_false . "[then:] "if this check fails, an exception is thrown. This is the expected result, so the test passes: we are done here: RETURN. "ok! ENDTRY. "only if for some reason there was NO exception, we reach this point. This is NOT what we expected. The test failed, so this is what we do: cl_abap_unit_assert=>fail( ). ENDMETHOD.
Questions / thoughts:
– how does this kind of presentation – code block with comments – work for you?
– how would I test the other way round? -> let the check pass? (Do I even need to test that ?)
– my public method is check_and_move_stock -> do some checks, and if all pass, create a warehouse task. Should that be 2 public methods instead ? ( I have more thoughts on that , but this is probably for another post)