You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Expected n, Actual m -- Wanted by not invoked <the qualified method> <custom message>
which can lead to head scratching when one tries to figure out why the verify fails.
Is the matcher wrong in the testmethod?
Is the code under test wrong?
Are the calls in the wrong order (fflib_InOrder use case)?
Since ApexMocks is recording all the actual method calls and the verify methods are comparing a single method call against all recorded calls of that method; it would seem useful to the developer to display an enumeration of the recorded method calls when this exception is thrown.
Here's an example where this would have helped me (example is a simplified version of the real code under test)
Code Under Test
public with sharing class MyCode {
public void doStuff(List<Id> list0, List<Id> list1) {
StuffService.add(list0);
list0.clear(); // pay attention to this line
StuffService.add(list1);
}
}
Service class being mocked
public with sharing class StuffServiceImpl implements IStuffService {
static List<id> ids = new List<Id>();
public void add(List<Id> idsToAdd) {
ids.addAll(idsToAdd);
}
}
Test method
@IsTest
private class MyCodeTest {
@IsTest
static void testInorder() {
// Given test data
Id[] mockIds = new List<Id> {
fflib_IDGenerator.generate(Account.SObjectType),
fflib_IDGenerator.generate(Account.SObjectType),
fflib_IDGenerator.generate(Account.SObjectType),
fflib_IDGenerator.generate(Account.SObjectType)
};
// Given mocks framework
fflib_ApexMocks mocks = new fflib_ApexMocks();
// Given mock Service
StuffServiceImpl mockStuffService = (StuffServiceImpl) mocks.mock(StuffServiceImpl.class);
// Given mock Service injected
Application.Service.setMock(IStuffService.class,mockStuffService);
// Given inOrderMocks
fflib_InOrder mocksInOrder =
new fflib_InOrder(mocks,new List<Object> {mockStuffService});
// Given code to test
MyCode myCode = new MyCode();
// When called with distinct sets of Ids
myCode.doStuff(new List<id> {mockIds[0],mockIds[1]},
new List<Id> {mockIds[2],mockIds[3]});
// Then verify order of calls to mock service
((StuffServiceImpl)mocksInOrder.verify(mockStuffService,mocks.calls(1)
.description('service sb called for ids[0] and [1]')))
.add(new List<Id> {mockIds[0],mockIds[1]});
((StuffServiceImpl)mocksInOrder.verify(mockStuffService,mocks.calls(1)
.description('service sb called for ids[2] and [3]')))
.add(new List<Id> {mockIds[2],mockIds[3]});
}
}
The first verify fails with
fflib_ApexMocks.ApexMocksException: In Order: Expected : 1, Actual: 0 -- Wanted but not invoked: StuffServiceImpl__sfdc_ApexStub.add(List<Id>). service sb called for ids[0] and [1].
...head scratching...
The reason why is that ApexMocks captures method non-primitive arguments by reference (rather than cloning them -- which is admittedly not always possible), so if the code under test changes the captured non-primitive argument before the ApexMocks verify is executed, the argument being compared (in my case):
((StuffServiceImpl)mocksInOrder.verify(mockStuffService,mocks.calls(1)
.description('service sb called for ids[0] and [1]')))
.add(new List<Id> {mockIds[0],mockIds[1]});
is no longer is equal to the argument that was captured because the code under test had cleared that argument! with list0.clear();
Five hours of my life went into discovering this after debugging the guts of ApexMocks and seeing that fflib_InOrder.verifyMethodCall was returning via getNextMethodCall() an argument of an empty list even though during method recording, the recorded arg was a list of two Ids. I should not have to dig into ApexMocks internals to see why the matching failed.
The text was updated successfully, but these errors were encountered:
the method
throwException
currently displayswhich can lead to head scratching when one tries to figure out why the
verify
fails.Since ApexMocks is recording all the actual method calls and the verify methods are comparing a single method call against all recorded calls of that method; it would seem useful to the developer to display an enumeration of the recorded method calls when this exception is thrown.
Here's an example where this would have helped me (example is a simplified version of the real code under test)
Code Under Test
Service class being mocked
Test method
The first verify fails with
...head scratching...
The reason why is that ApexMocks captures method non-primitive arguments by reference (rather than cloning them -- which is admittedly not always possible), so if the code under test changes the captured non-primitive argument before the ApexMocks
verify
is executed, the argument being compared (in my case):is no longer is equal to the argument that was captured because the code under test had cleared that argument! with
list0.clear();
Five hours of my life went into discovering this after debugging the guts of ApexMocks and seeing that
fflib_InOrder.verifyMethodCall
was returning viagetNextMethodCall()
an argument of an empty list even though during method recording, the recorded arg was a list of two Ids. I should not have to dig into ApexMocks internals to see why the matching failed.The text was updated successfully, but these errors were encountered: