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

Method call counts persist for entire testMethod process #50

Open kvizcarra opened 7 years ago

kvizcarra commented 7 years ago

Inside a testMethod, we loop through a list of TestCases, stub dependencies, and verify behavior. The problem we've encountered is the verify call will fail on the second test case instance saying that the method was expected to be called once but actually was called twice. Instantiating ApexMocks and the mock dependencies inside the loop doesn't work. What does work is if we pass unique inputs to the mock method we are verifying for each test case instance.

Example

static testMethod void getUsersTest() {
    for (TestCase testCase : getTestCases()) {
        fflib_ApexMocks mocks = new fflib_ApexMocks();

        IUserRepository mockUserRepository = (IUserRepository)mocks.mock(IUserRepository.class);

        [...]
        ((IUserRepository) mocks.verify(mockUserRepository, 1)).getUsers(testCase.nameFilter);
        [...]
    }
}

private class TestCase {
    string nameFilter;
    integer someOtherFilter;

    TestCase(string nameFilter, integer someOtherFilter) {
        this.nameFilter = nameFilter;
        this.someOtherFilter = someOtherFilter;
    }
}

These test cases would fail:

private static List<TestCase> getTestCases() {
    return new List<TestCase>{
        new TestCase('Bob', null),
        new TestCase('Bob', 0),
        new TestCase('Bob', 5),
    };
}

And these would succeed:

private static List<TestCase> getTestCases() {
    return new List<TestCase>{
        new TestCase('Bob', null),
        new TestCase('Bib', 0),
        new TestCase('Berb', 5),
    };
}

Possible cause

After some digging into the library, I may have found what's causing this. It looks like the library is using fflib_MethodCountRecorder.methodArgumentsByTypeName to keep track of the method calls, but since it's static it persists for the entire testMethod process.

dfruddffdc commented 7 years ago

This is similar to the issue raised in #29. As a workaround, you can stub instances of objects independently using ApexMocksConfig.HasIndependentMocks.

See #42 for examples of its usage.

Marked as an enhancement request.

kvizcarra commented 7 years ago

Confirmed the workaround works