Enhanced Mock Mocks

Well color me surprised, my last article on mocking in apex was, well, a little more popular than I thought it would be. I was happy that so may people enjoyed it, but it got me thinking, “Bob, you handsome and brilliant, yet refreshingly humble man, you can do more for your fans!” After an obligatory back patting, I set off to add more features. This will build entirely off of the last article. In fact, you are doing yourself a disservice if you don’t read it post haste.

We start with a change to add parameter matcher, a handy feature for times when you are not 100% sure the value that is going into you method. All we need is an enum.

This is the bare minimum to work while still providing room for enhancement. The only thing in this enum is the value anyVal. What we are saying is when this is used, accept any value. Next I modified my interface, services and test to give the method getAuthCode a Datetime parameter. The OrderService will pass in Datetime.now(), making this almost impossible to mock without matchers. There also needs to be a change in Mock maker to handle this new condition.

It isn’t much different than it was two weeks ago, except now it checks if the parameter is a matcher. If it is, and since there is only one possible value it could be, we just skip any check on the parameter and continue to the next. Now we can change our test to work with this new code.

Now our call to getAuthCode will work no matter what we pass in. A quick test run shows both tests passing… but that isn’t right, now is it? We only changed one test yet both still pass. It isn’t enough to simply check the parameters, we need to check the number of them as well. Otherwise our loop could give false positives like in this case, or throw exceptions. Let’s put a halt to that right now.

One extra line asserts that the number of parameters passed in is the same as those expected.

There is another case we are still not testing for. If you remember last time, I used mocks to return a purposeful bad value to test out some error handling. What if we wanted to test what happens when the service we are mocking throws an exception itself? We need some more code for this one but before that, we need an exception to throw.

Phew, that was a lot of work, but I soldier on. Next is some code in our service to expect such an exception.

 

Now we need to get MockMaker to throw the exception at the right time.

This getCall method keeps getting all of the attention. Another conditional now checks if the return value is actually an exception and if so, it throws it. The only thing left is the test.

The only real difference here is that the addCall for processPayment has an exception passed into it and the end assert reflects the caught exception.

With just a bit of work, MockMaker now checks the quantity of parameters, uses matchers to check for values that might not be known when the test is started, and throws exceptions on command. While not on par with some other language’s mock suits, it can go a long way to making life easier for a developer.

3 comments

  1. Jesse Altman says:

    I love your sense of humor Bob! You had me laughing pretty good for a Monday morning with your line: “I was happy that so may people enjoyed it, but it got me thinking, “Bob, you handsome and brilliant, yet refreshingly humble man, you can do more for your fans!”

    Very good read as well. With mocks, we get closer and closer to real unit tests each day. I like the idea of testing just a single “unit” of code, rather than having to tests all of the units “integrating” together! There is a phrase for that type of testing, and it isn’t unit testing!

Leave a Reply

Your email address will not be published. Required fields are marked *