Skip to content

Removing some clutter from ApexMocks syntax #70

Open
@mischkes

Description

@mischkes

Hey guys,

I recently started working with apex-mocks and I love it. The only thing I didn't like and where it falls a bit short with regards to Mockito is the amount of clutter in the code. Some is due to the Salesforce restrictions (no generics...) but some seemed unnecessary.

So I played arround with it a bit and found three changes that improve this. The results can be seen here: https://github.com/mischkes/fflib-apex-mocks/tree/feature/poc-for-less-clutter#a-more-complicated-case

We are already using this code in production, but it is not yet library-grade. If you are interested I would be happy to improve the code and make some pull requests.

The changes are:

Create a Utility class that encapsulates ApexMocks and Match

  • See https://github.com/mischkes/fflib-apex-mocks/blob/feature/poc-for-less-clutter/src/classes/fflib_Mock.cls
  • this is actually the same way Mockito is doing it
  • I would advise Projects using fflib-apex-mocks to rename this file (eg. to 'Mocks' as in the example or even 'Mk') to further reduce clutter. This is easily possible as there are no dependencies on fflib_Mock, so no other class has to be changed.
  • This removes the clutter from constructing fflib_ApexMocks
  • This removes clutter from writing fflib_Match
  • This removes more clutter for more complex use-cases, e.g. by the use of fflib_Mock.Answer)
  • This also creates a single-place-of use, which makes it easier for Newbies. "Just look at fflib_Mock"
  • This also hides away some of the public Methods intended for use internally, like handleMethodCall or mockNonVoidMethod
  • This change requires almost no change to the existing code. Currently I'm subclassing fflib_Match from fflib_Mock for convenienve, but event that could be wrapped. Which might be a good Idea to hide some internal methods like getAndClearMatchers.

Make start/stopStubbing unnecessary

  • there is/was probably some use-case why those methods makes sense, but I didn't see it
  • the main change was to always return a value in fflib_ApexMocks.mockNonVoidMethod, and move the actual parameter storing to fflib_ApexMocks.when
  • This remove the clutter from the startStubbing() / stopStubbing() methods
  • this is a minor breaking change, as mocking a method that was previously mocked to throw an exception will throw this exception during mocking. Mockito uses doReturn() statements for this case, which could be implemented
  • this also removes the curent possibility to check for incomplete stubbing. I guess it could still be done by setting a flag inside when() and clearing it on then()

Record call history inside methods

  • this change is probably mostly a matter of taste
  • I never really liked the way complex argument checks are done in Mockito, with the ArgumentCaptor and all. And ApexMocks is following Mockito here.
  • I really like the way jasmine is handling this and implemented it in the same way: simply storing the call history in the method (here: the Method mock object)
  • this removes the clutter to create the captor, then verifying, and then getting the object from the captor
  • this was also a minor change in the code

All in all these changes remove approx. 50% of the necessary mocking code, which I think is really a lot.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions