apex-enterprise-patterns / fflib-apex-mocks

An Apex mocking framework for true unit testing in Salesforce, with Stub API support
BSD 3-Clause "New" or "Revised" License
423 stars 214 forks source link

Small enhancement to ReadMe #47

Open cropredy opened 7 years ago

cropredy commented 7 years ago

For those of us who didn't come from a Java background and hence weren't exposed to Mockito, the Readme section when() dependency stubbing is maddeningly tantalizing. The obvious question one immediately asks is what if you don't care what the arg values are in the stubbed method? After much web searching and inspection of fflib_ApexMocksTest I realized there was a whole wealth of matchers that can be used not only in the verify() but also in the when()!

A small additional example in the Readme would inspire and direct the reader to the supported matchers in fflib_Match.

This framework is pretty powerful stuff but as

dfruddffdc commented 7 years ago

Yes, I agree wholeheartedly. I'll try and sort some of these things out and report back after.

dfruddffdc commented 7 years ago

Hi cropredy, I finally got round to working on this.

We could definitely be doing a much better job with our docs, and you're right that it's a major barrier to adoption.

I think part of the problem is that the tests inside ApexMocks are a little contrived. So I put together a little SFDX sample app, with more realistic unit tests.

I'm using the Stub API, matchers, answers, and discuss different techniques for generating mocks and patterns for dependency injection - these are all covered in detail in the readme. https://github.com/dfruddffdc/apex-mocks-sfdx

I'll port over the documentation into this repo's wiki at some point. Until then, hopefully my new sample app will help clarify things.

cropredy commented 7 years ago

David - I look forward to diving into this. After reading it, I may need to amend my blog posts on ApexMocks http://cropredysfdc.com/2017/10/11/apex-mocks-and-enterprise-patterns-first-in-a-series/, written after exploiting the technique a few times in our org :-)

Eric

On Sat, Nov 25, 2017 at 11:53 PM, David Frudd notifications@github.com wrote:

Hi cropredy, I finally got round to working on this.

We could definitely be doing a much better job with our docs, and you're right that it's a major barrier to adoption.

I think part of the problem is that the tests inside ApexMocks are a little contrived. So I put together a little SFDX sample app, with more realistic unit tests.

I'm using the Stub API, matchers, answers, and discuss different techniques for generating mocks and patterns for dependency injection - these are all covered in detail in the readme. https://github.com/dfruddffdc/apex-mocks-sfdx

I'll port over the documentation into this repo's wiki at some point. Until then, hopefully my new sample app will help clarify things.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/financialforcedev/fflib-apex-mocks/issues/47#issuecomment-346990942, or mute the thread https://github.com/notifications/unsubscribe-auth/ACNrckO9bLQuLLn078r4E6j-3tc9HzwTks5s6RkSgaJpZM4Oxe2h .

afawcett commented 7 years ago

@dfruddffdc nice work! 👍

cropredy commented 7 years ago

David -- I read the Readme in your ApexMocks project https://github.com/dfruddffdc/apex-mocks-sfdx and it looks excellent. I even learned something about fflib_System which was new to me.

Some suggested additional doc that would help new users:

The unit test vs system test paragraph at the end is an interesting one and can be further motivated with:

One must absolutely have systems tests for Selectors as if they are only mocked, you have no way of proving that the filter criteria was coded right or that the fields needed by the selector consumer are even fetched! One must have system tests for classes that update the database as mocking the Unit Of Work layer won't execute validation rules, fire downstream triggers, workflows, process builder flows, or exercise sharing rules

Lastly, I've also been making notes in my Packt Publishing "Mockito" book on which Mockito features (i.e. specific Matchers) are not implemented in ApexMocks but you might already have a good list and that would merit inclusion in the Readme.

Eric

On Sun, Nov 26, 2017 at 11:22 AM, Andrew Fawcett notifications@github.com wrote:

@dfruddffdc https://github.com/dfruddffdc nice work! 👍

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/financialforcedev/fflib-apex-mocks/issues/47#issuecomment-347031597, or mute the thread https://github.com/notifications/unsubscribe-auth/ACNrci-bcAzJAr1d7DrJIR8Vh89Ucdeoks5s6bpegaJpZM4Oxe2h .

afawcett commented 7 years ago

@cropredy thats an excellent tip, we should for sure reference that on the readme as being complementary. I also found that i wanted to mock complex selector responses and thus the following method was born, https://github.com/financialforcedev/fflib-apex-mocks/blob/master/src/classes/fflib_ApexMocksUtils.cls#L67.

dfruddffdc commented 6 years ago

@cropredy Thanks for the detailed feedback, very useful!

cropredyHelix commented 5 years ago

While puzzling over why one of my mocks wasn't working I reread the Readme.md last night and I had two additional thoughts:

  1. There is no link in the related refs to https://github.com/dfruddffdc/apex-mocks-sfdx which explains practical techniques for dependency injection
  2. AFAIK, there is no example in ApexMocks.Test that illustrates dependency injection for the fflib_MyList class that is used for all the testing.

Leading me to suggest that this section of the readme.md be enhanced as follows:

when() dependency stubbing

        // given mocks
    fflib_ApexMocks mocks = new fflib_ApexMocks();
    fflib_MyList.IList mockList = (fflib_MyList.IList)mocks.mock(fflib_MyList.class);

    mocks.startStubbing();
    mocks.when(mockList.get(0)).thenReturn('bob');
    mocks.when(mockList.get(1)).thenReturn('fred');
    mocks.stopStubbing();

        // given mocks injected (see also https://github.com/dfruddffdc/apex-mocks-sfdx)
        Bar b = new Bar(mockList);
        // when Bar invoked
        String result = b.doStuff();
        // then verify
        System.assertEquals(result, 'bob,fred','doStuff assembles a comma-separated list');

where the object under test is:

public class Bar 
  private fflib_MyList.IList myList;  // interface so real and mock can be used
  public Bar() {this.myList = new fflib_MyList.IList();} // normal PROD
  public Bar(fflib_MyList.IList mockMyList) {this.myList = mockMyList;} // for unit testing

  String public doStuff() {
  String[] resultVals = new List<String>(); 
  for (Integer i=0; i < 2; i++) {
    myList.add(i);
    resultVals.add(myList.get(i);
  }
  return String.join(resultVals,',');
}

So - why did I add this bit?