Counters in the InOrder world: times()

If you are reading this post, probably you had already a glance to my previous post about the Counters. You have probably noticed that the Counters functionality was somehow incomplete. Some of the counter where available for the classic verification but not for the ordered verification.

But not anymore.

Apex Mocks it’s getting more flexible and powerful allowing you to specify strict and loose counters in the inOrder verification.

Let’s go through them one by one and discover their power.

times()

((ISoftwareDeveloper) inOrder.verify(
    mockProductiveDeveloper, MY_MOCKS.times(15))).drinkCoffe();

You can immediately understand that our software is having quite a lot of coffees during the day. But there are some details that need to be mentioned. Let’s have a look at this snippet of pseudo code.

1 softDev.writeSomeCode();
2 softDev.writeSomeCode();
3 softDev.drinkCoffe();

4 softDev.writeSomeCode();
5 softDev.blameSlowNetwork();

6 softDev.writeSomeCode();
6 softDev.writeSomeCode();
7 softDev.gitCommit();

We all are productive developers, so let’s concentrate on the writing of the code, and verify how many times the code has been written.

The times allows us to check how many times the method has been called, and this verification is not strict. What does it mean in code? If we write those verify as separate tests

((ISoftwareDeveloper) inOrder.verify(
    mockProductiveDeveloper, MY_MOCKS.times(2))).writeSomeCode();

((ISoftwareDeveloper) inOrder.verify(
    mockProductiveDeveloper, MY_MOCKS.times(1))).drinkCoffe();

and

((ISoftwareDeveloper) inOrder.verify(
    mockProductiveDeveloper, MY_MOCKS.times(3))).writeSomeCode();

((ISoftwareDeveloper) inOrder.verify(
    mockProductiveDeveloper, MY_MOCKS.times(1))).blameSlowNetwork();

they would both pass.

Yep, you read correctly, they both pass. Why? It’s related to the instances consumed in the verification. For each test, the inOrder goes through all the instances of the mock that we are verifying and sequentially consumes the available invocations.

The first tests first check that writeSomeCode() method is called twice, then looks for the drinkCoffe() and it’s happy. Quite straight forward.

The second Test instead is a bit more tricky. This needs three instances of the writeSomeCode(). Starting from the beginning it has two instances, then have the drinckCoffe() in the middle that is ignored and then it finds the third. After that, the instance available to be verified is blameSlowNetwork().

I’m sure you can tell me how many available instances there are for the writeSomeCode() before our dev would final commit the work on git.

On the other side

((ISoftwareDeveloper) inOrder.verify(
    mockProductiveDeveloper, MY_MOCKS.times(4))).writeSomeCode();

((ISoftwareDeveloper) inOrder.verify(
    mockProductiveDeveloper, MY_MOCKS.times(1))).gitCommit();

and

((ISoftwareDeveloper) inOrder.verify(
mockProductiveDeveloper, MY_MOCKS.times(3))).writeSomeCode();
((ISoftwareDeveloper) inOrder.verify(
mockProductiveDeveloper, MY_MOCKS.times(1))).blameSlowNetwork();
((ISoftwareDeveloper) inOrder.verify(
mockProductiveDeveloper, MY_MOCKS.times(1))).writeSomeCode();

both would fail.

One last detail, the default verification for the InOrder is now “times(1)”. that means that I could happily not specify in my examples whether instead, I kept for readability.

As you can see the power and the flexibility of the InOrder verification have grown with this new counter adding a functionality that was some how missing.

Advertisements

Counters in the InOrder world: atLeast() vs. calls()

This is another chapter of our little story through the ApexMocks counters for the inOrder verification.

You have probably already encountered the first chapter about the inOrder verification.

You have probably noticed that those verifications were some how incomplete in their functionality, but not anymore.

The times() added the possibility to verify the exact number of calls, and then the atLeast() get along. The atLeast() and calls() both set the minimum number of calls that are expected for that method, but they behave differently. The atLeast() is greedy, instead the calls() is not.

Greedy? Not greedy? What does it mean?

To explain the greedy concept we first need to talk about the invocation consumed.

The inOrder stores the invocations methods called on the mocked instance sequentially, in a list. Then when we verify the inOrder goes through this list and “consume” those invocations.

The atLeast(), being greedy, would consume all the invocations that match the method under verification instead, the calls() would consume only those that have been verified.

Let’s see with some pseudo code.

1 softDev.writeSomeCode(); 
2 softDev.writeSomeCode(); 
3 softDev.drinkCoffe(); 
4 softDev.writeSomeCode(); 
5 softDev.blameSlowNetwork(); 
6 softDev.writeSomeCode(); 
7 softDev.writeSomeCode(); 
8 softDev.gitCommit();

performing the following verify

((ISoftwareDeveloper) inOrder.verify( 
     mockProductiveDeveloper, MY_MOCKS.calls(2))).writeSomeCode();

the next available invocation to be verified in this case would be the drinkCoffe() at line 3.

Using the atLeast() instead

((ISoftwareDeveloper) inOrder.verify( 
    mockProductiveDeveloper, MY_MOCKS.atLeast(2))).writeSomeCode();

since it consumes all the invocations that match our method, the next method that is available to be verified is gitCommit() at line 8.

Apex Mocks behaves as close possible to Mockito and for the greedy verification, this page of the Mockito documentation would explain how this concept works.

A special version of the atLeast() is also available: atLeastOnce(). Guess how many time is expected to be called…

The adding of atLeast() counter for the inOrder verification it narrows down the gap of funcionality between ApexMocks and Mockito, giving more flexibility to your mock verification.

Happy mocking.

Stub multiple calls

One of the basics concepts in Mocking is the stubbing.

Wikipedia gives us this definition of stubbing:

“A method stub or simply stub in software development is a piece of code used to stand in for some other programming functionality. ”

In ApexMocks we can stub a method to return a value, or to throw an exception. We can even specify a custom answer when we need more flexibility and power.

Historically the stubbing with ApexMocks can handle only one value at the time.

What if you need to stub a method to return different values or different exceptions each time is called. Well, you could write an Answer and shape what you need, or…

Mockito, from which ApexMock get inspiration, have a specific syntax for that so why ApexMock shouldn’t have as well?

Now you can.

Every one of us has a friend that is not reliable time wise. They great, but they almost cannot make in time at a meeting. Everyone turned up, but not Franck. Then if you call them asking for an estimate of the time they would be there you get each time different time values… and potentially different excuses but for now, let’s keep it simple and concentrate on the times.

MY_MOCKS.when( everyoneTurnedUp.callFrankToFiguredOutWhenHisGonnaArrive()).
    thenReturn(new Time(15 minutes)).
    thenReturn(new Time(20 minutes)).
    thenReturn(new Time(10 minutes)).
    thenThrow(newBeInTimeException('we are all here, hurry up!')). //you are fed up of waiting and shout at Franck to be quicker
    thenReturn(new Time(0 minute)); //he finally arrived

When then you call the callFrankToFiguredOutWhenHisGonnaArrive() this would return 15 the first time, 20 the second, 10 the third, then would throw an exception for the fourth invocation, and for all the other subsequences calls would return zero.

This is possible because those methods can be chained together and define precisely what you need.

To be fair you could write that stubbing in a more compact way using the thenReturnMulti() stubbing method:

MY_MOCKS.when( everyoneTurnedUp.callFrankToFiguredOutWhenHisGonnaArrive()).
    thenReturnMulti(new List<Time>{minutes15, minutes20, minutes10}).
    thenThrow(new BeInTimeException('we are all here, hurry up!')).
    thenReturn(new Time(0 minute));

Similarly, there is the possibility to specify a sequence of Exception that you want to throw sequentially, with the thenThrowMulti() and a list of exceptions as the parameter.

thenReturnMulti() and thenThrowMulti() are not perfectly compliant with Mockito. Mockito uses the same name for the single argument version and the multiple argument version, using an iterable as the parameter of the multi. In Apex we are more limited. The thenReturnMulti() needs to take as a parameter  a list of objects,  and the thenReturn() needs an object. A list of objects is still an object, isn’t it?

If we stubbed N times a method and then the method is called more times than N, after N the value returned would be the one in the last stub. In our case after the fifth time, it would return constantly zero.

One last detail, if you stub the same method multiple times the last stub override the others, for example:

MY_MOCKS.when( everyoneTurnedUp.callFrankToFiguredOutWhenHisGonnaArrive()).
    thenReturn(new Time(5 minutes));

MY_MOCKS.when( everyoneTurnedUp.callFrankToFiguredOutWhenHisGonnaArrive()).
    thenReturn(new Time(10 minutes));

MY_MOCKS.when( everyoneTurnedUp.callFrankToFiguredOutWhenHisGonnaArrive()).
    thenReturn(new Time(11 minutes));

the last stub would override the two previous of 5 and 10 minutes.

The stubbing for sequential calls gives you the flexibility to cover those cases that a simple return is not enough, but with out need to write a custom answer.

Happy Mocking.