Repository: financialforcedev/fflib-apex-mocks
Branch: master
Commit: 0f37f7677970
Files: 85
Total size: 489.9 KB
Directory structure:
gitextract_1z2z19yr/
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ └── feature_request.md
│ └── workflows/
│ ├── deploy.and.test.yml
│ └── manage.sf.api.versions.yml
├── .gitignore
├── LICENSE
├── README.md
├── config/
│ └── project-scratch-def.json
├── sfdx-project.json
└── sfdx-source/
└── apex-mocks/
├── main/
│ └── classes/
│ ├── fflib_Answer.cls
│ ├── fflib_Answer.cls-meta.xml
│ ├── fflib_AnyOrder.cls
│ ├── fflib_AnyOrder.cls-meta.xml
│ ├── fflib_ApexMocks.cls
│ ├── fflib_ApexMocks.cls-meta.xml
│ ├── fflib_ApexMocksConfig.cls
│ ├── fflib_ApexMocksConfig.cls-meta.xml
│ ├── fflib_ApexMocksUtils.cls
│ ├── fflib_ApexMocksUtils.cls-meta.xml
│ ├── fflib_ArgumentCaptor.cls
│ ├── fflib_ArgumentCaptor.cls-meta.xml
│ ├── fflib_IDGenerator.cls
│ ├── fflib_IDGenerator.cls-meta.xml
│ ├── fflib_IMatcher.cls
│ ├── fflib_IMatcher.cls-meta.xml
│ ├── fflib_InOrder.cls
│ ├── fflib_InOrder.cls-meta.xml
│ ├── fflib_Inheritor.cls
│ ├── fflib_Inheritor.cls-meta.xml
│ ├── fflib_InvocationOnMock.cls
│ ├── fflib_InvocationOnMock.cls-meta.xml
│ ├── fflib_Match.cls
│ ├── fflib_Match.cls-meta.xml
│ ├── fflib_MatcherDefinitions.cls
│ ├── fflib_MatcherDefinitions.cls-meta.xml
│ ├── fflib_MatchersReturnValue.cls
│ ├── fflib_MatchersReturnValue.cls-meta.xml
│ ├── fflib_MethodArgValues.cls
│ ├── fflib_MethodArgValues.cls-meta.xml
│ ├── fflib_MethodCountRecorder.cls
│ ├── fflib_MethodCountRecorder.cls-meta.xml
│ ├── fflib_MethodReturnValue.cls
│ ├── fflib_MethodReturnValue.cls-meta.xml
│ ├── fflib_MethodReturnValueRecorder.cls
│ ├── fflib_MethodReturnValueRecorder.cls-meta.xml
│ ├── fflib_MethodVerifier.cls
│ ├── fflib_MethodVerifier.cls-meta.xml
│ ├── fflib_QualifiedMethod.cls
│ ├── fflib_QualifiedMethod.cls-meta.xml
│ ├── fflib_QualifiedMethodAndArgValues.cls
│ ├── fflib_QualifiedMethodAndArgValues.cls-meta.xml
│ ├── fflib_System.cls
│ ├── fflib_System.cls-meta.xml
│ ├── fflib_VerificationMode.cls
│ └── fflib_VerificationMode.cls-meta.xml
└── test/
└── classes/
├── fflib_AnswerTest.cls
├── fflib_AnswerTest.cls-meta.xml
├── fflib_AnyOrderTest.cls
├── fflib_AnyOrderTest.cls-meta.xml
├── fflib_ApexMocksTest.cls
├── fflib_ApexMocksTest.cls-meta.xml
├── fflib_ApexMocksUtilsTest.cls
├── fflib_ApexMocksUtilsTest.cls-meta.xml
├── fflib_ArgumentCaptorTest.cls
├── fflib_ArgumentCaptorTest.cls-meta.xml
├── fflib_IDGeneratorTest.cls
├── fflib_IDGeneratorTest.cls-meta.xml
├── fflib_InOrderTest.cls
├── fflib_InOrderTest.cls-meta.xml
├── fflib_InheritorTest.cls
├── fflib_InheritorTest.cls-meta.xml
├── fflib_MatchTest.cls
├── fflib_MatchTest.cls-meta.xml
├── fflib_MatcherDefinitionsTest.cls
├── fflib_MatcherDefinitionsTest.cls-meta.xml
├── fflib_MethodArgValuesTest.cls
├── fflib_MethodArgValuesTest.cls-meta.xml
├── fflib_MyList.cls
├── fflib_MyList.cls-meta.xml
├── fflib_QualifiedMethodAndArgValuesTest.cls
├── fflib_QualifiedMethodAndArgValuesTest.cls-meta.xml
├── fflib_QualifiedMethodTest.cls
├── fflib_QualifiedMethodTest.cls-meta.xml
├── fflib_SystemTest.cls
└── fflib_SystemTest.cls-meta.xml
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
(A clear and concise description of what the bug is.)
**To Reproduce**
(Please provide a public github repo with a full SFDX project that demonstrates the problem. If the repro case can be followed with a single example Apex class against a scratch org with just the fflib-apex-mocks project deployed into it, you don't need to provide a github repo)
Steps to reproduce the behavior:
1. Create a scratch org as follows....
2. Run the following Anonymous Apex....
3. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots and text of error observed**
If applicable, add screenshots to help explain your problem. Also, paste the text of the raw error into the issue as well so that it can be found by others via search.
**Version**
Did you try to reproduce the problem against the latest fflib-apex-mocks code?
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
================================================
FILE: .github/workflows/deploy.and.test.yml
================================================
name: Create a Scratch Org, Push Source and Run Apex Tests
on:
push:
pull_request_target:
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2 #Check out this repo
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Install SF CLI and authorize DevHub
uses: apex-enterprise-patterns/setup-sfdx@v2 #We're using a fork of https://github.com/sfdx-actions/setup-sfdx for safety
with:
sfdx-auth-url: ${{ secrets.DEVHUB_SFDXURL }}
- name: Setup the config parameters needed
run: sf config set target-dev-hub SFDX-ENV --global #Even though the setup-sfdx action uses --setdefaultdevhubusername, it doesn't seem to stick since it uses --setdefaultusername so we brute force it here
- name: Create the scratch org
run: sf org create scratch --definition-file config/project-scratch-def.json --set-default --duration-days 1 --no-track-source
- name: Deploy and compile the codebase
run: sf project deploy start
- name: Run the core framework tests
run: sf apex run test --wait 5
- name: Destroy scratch org
run: sf org delete scratch --no-prompt
if: always()
================================================
FILE: .github/workflows/manage.sf.api.versions.yml
================================================
name: Manage SF API Versions
on:
workflow_dispatch:
inputs:
api-version:
description: 'api version in the format XX e.g 58'
required: true
type: string
jobs:
update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: apex-enterprise-patterns/manage-sf-api-version@v1.0.0
with:
api-version: ${{inputs.api-version}}
- uses: peter-evans/create-pull-request@v5
with:
title: 'Bump API Versions to ${{inputs.api-version}}.0'
body: 'Automatically bumped by GitHub Actions '
branch: 'devops/bump-api-versions-v${{inputs.api-version}}.0'
commit-message: 'chore: bump api to v${{inputs.api-version}}.0'
================================================
FILE: .gitignore
================================================
# General Project related
.DS_Store
target/
temp/
/deploy/*
/debug/
**/dep-dir.txt
*.prefs
build.properties
/sfdx-source/apex-mocks/main/default
# MavensMate IDE related
*mm.log
*.sublime-build
*.sublime-project
*.sublime-settings
*.sublime-workspace
.sublime-project
.tm_properties
# Eclipse IDE Related
.project
.settings/
salesforce.schema
Referenced Packages/
# VS Code IDE Related
.vscode/
.history/
# Illuminated Cloud Related
.idea/
IlluminatedCloud
# SFDX Related
.sfdx/
.sf/
sfdx-source/untracked/
.execanon
# NPM Related
package.json
/node_modules
package-lock.json
sfdx-source/group*
research/
================================================
FILE: LICENSE
================================================
Copyright (c), FinancialForce.com, inc
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the FinancialForce.com, inc nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: README.md
================================================
# FFLib ApexMocks Framework

ApexMocks is a mocking framework for the Salesforce Lightning Apex language.
It derives its inspiration from the well known Java mocking framework [Mockito](https://site.mockito.org/)
## Using ApexMocks on the Salesforce Lightning Platform
ApexMocks allows you to write tests to both verify behavior and stub dependencies.
An assumption is made that you are using some form of [Dependency Injection](http://en.wikipedia.org/wiki/Dependency_injection) - for example passing dependencies via a constructor:
```Java
public MyClass(ClassA.IClassA dependencyA, ClassB.IClassB dependencyB)
```
This allows you to pass mock implementations of dependencies A and B when you want to unit test MyClass.
Lets assume we've written our own list interface fflib_MyList.IList that we want to either verify or stub:
```Java
public class fflib_MyList implements IList
{
public interface IList
{
void add(String value);
String get(Integer index);
void clear();
Boolean isEmpty();
}
}
```
### verify() behaviour verification
```Java
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList.IList mockList = (fflib_MyList.IList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
// Then
((fflib_MyList.IList) mocks.verify(mockList)).add('bob');
((fflib_MyList.IList) mocks.verify(mockList, fflib_ApexMocks.NEVER)).clear();
```
If the method wasn't called the expected number of times, or with the expected arguments, verify will throw an exception.
The exception message contains details of the expected and actual invocations:
```
EXPECTED COUNT: 1
ACTUAL COUNT: 0
METHOD: EmailService__sfdc_ApexStub.sendTo(String)
---
ACTUAL ARGS: ("user-two@example.com")
---
EXPECTED ARGS: [[contains "user-one"]]
```
### when() dependency stubbing
```Java
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();
```
## Utilties
### Setting a read-only field, such as a formula
```Java
Account acc = new Account();
Integer mockFormulaResult = 10;
acc = (Account)fflib_ApexMocksUtils.setReadOnlyFields(
acc,
Account.class,
new Map {Account.Your_Formula_Field__c => mockFormulaResult}
);
System.assertEquals(mockFormulaResult, acc.Your_Formula_Field__c);
```
## Stub API
Using Salesforce's [Stub API](https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_testing_stub_api.htm), stub objects are generated dynamically at run time.
```Java
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
```
## Documentation
* [ApexMocks Framework Tutorial](http://code4cloud.wordpress.com/2014/05/06/apexmocks-framework-tutorial/)
* [Simple Dependency Injection](http://code4cloud.wordpress.com/2014/05/09/simple-dependency-injection/)
* [ApexMocks Generator](http://code4cloud.wordpress.com/2014/05/15/using-apex-mocks-generator-to-create-mock-class-definitions/)
* [Behaviour Verification](http://code4cloud.wordpress.com/2014/05/15/writing-behaviour-verification-unit-tests/)
* [Stubbing Dependencies](http://code4cloud.wordpress.com/2014/05/15/stubbing-dependencies-in-a-unit-test/)
* [Supported Features](http://code4cloud.wordpress.com/2014/05/15/apexmocks-supported-features/)
* [New Improved apex-mocks-generator](http://code4cloud.wordpress.com/2014/06/27/new-improved-apex-mocks-generator/)
* [ApexMocks Improvements - exception stubbing, base classes and more](http://code4cloud.wordpress.com/2014/11/05/apexmocks-improvements-exception-stubbing-inner-interfaces-and-mock-base-classes/)
* [Matchers](http://superdupercode.blogspot.co.uk/2016/03/apex-mocks-matchers.html)
* [ApexMock blogs from Jesse Altman](http://jessealtman.com/tag/apexmocks/)
* [Order of calls verification](https://xonoxforce.wordpress.com/2017/03/26/inorder-verify/)
* [Answering](https://xonoxforce.wordpress.com/2017/03/31/answering-with-apex-mocks/)
* [Counters](https://xonoxforce.wordpress.com/2017/04/01/counters-in-apex-mocks-verifications/)
* [Troubleshooting](https://salesforce.stackexchange.com/questions/252460/my-apexmocks-arent-working-what-could-be-wrong)
================================================
FILE: config/project-scratch-def.json
================================================
{
"orgName": "apex-mocks",
"edition": "Developer",
"settings": {
"lightningExperienceSettings": {
"enableS1DesktopEnabled": true
}
}
}
================================================
FILE: sfdx-project.json
================================================
{
"packageDirectories": [
{
"path": "sfdx-source/apex-mocks",
"default": true
}
],
"namespace": "",
"sfdcLoginUrl": "https://login.salesforce.com",
"sourceApiVersion": "63.0"
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_Answer.cls
================================================
/*
Copyright (c) 2017 FinancialForce.com, inc. All rights reserved.
*/
/**
* Interface for the answering framework.
* This interface must be implemented inside the test class and implement the call back method answer.
* @group Core
*/
@NamespaceAccessible
public interface fflib_Answer
{
/**
* Method to be implemented in the test class to implement the call back method.
* @param invocation The invocation on the mock.
* @throws The exception to be thrown.
* @return The value to be returned.
*/
Object answer(fflib_InvocationOnMock invocation);
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_Answer.cls-meta.xml
================================================
63.0
Active
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_AnyOrder.cls
================================================
/*
Copyright (c) 2017 FinancialForce.com, inc. All rights reserved.
*/
/**
* 'Classic' invocation verifier - checks that a method was called with the given arguments the expected number of times.
* The order of method calls is not important.
* @group Core
*/
@NamespaceAccessible
public class fflib_AnyOrder extends fflib_MethodVerifier
{
/*
* Verifies a method was invoked the expected number of times, with the expected arguments.
* @param qualifiedMethod The method to be verified.
* @param methodArg The arguments of the method that needs to be verified.
* @param verificationMode The verification mode that holds the setting about how the verification should be performed.
*/
protected override void verify(
fflib_QualifiedMethod qm,
fflib_MethodArgValues expectedArguments,
fflib_VerificationMode verificationMode)
{
List expectedMatchers = fflib_Match.Matching ? fflib_Match.getAndClearMatchers(expectedArguments.argValues.size()) : null;
List actualArguments = fflib_MethodCountRecorder.getMethodArgumentsByTypeName().get(qm);
Integer methodCount = getMethodCount(expectedArguments, expectedMatchers, actualArguments);
String qualifier = '';
Integer expectedCount = null;
if((verificationMode.VerifyMin == verificationMode.VerifyMax) && methodCount != verificationMode.VerifyMin)
{
expectedCount = verificationMode.VerifyMin;
}
else if (verificationMode.VerifyMin != null && verificationMode.VerifyMin > methodCount)
{
expectedCount = verificationMode.VerifyMin;
qualifier = ' or more times';
}
else if (verificationMode.VerifyMax != null && verificationMode.VerifyMax < methodCount)
{
expectedCount = verificationMode.VerifyMax;
qualifier = ' or fewer times';
}
if (expectedCount != null)
{
throwException(qm, '', expectedCount, qualifier, methodCount, verificationMode.CustomAssertMessage, expectedArguments, expectedMatchers, actualArguments);
}
}
private Integer getMethodCount(fflib_MethodArgValues methodArg, List matchers, List methodArgs)
{
Integer retval = 0;
if (methodArgs != null)
{
if (matchers != null)
{
for (fflib_MethodArgValues args : methodArgs)
{
if (fflib_Match.matchesAllArgs(args, matchers))
{
capture(matchers);
retval ++;
}
}
}
else
{
return countCalls(methodArgs, methodArg);
}
}
return retval;
}
private Integer countCalls(List methodArgs, fflib_MethodArgValues methodArg)
{
Integer count = 0;
for(fflib_MethodArgValues arg: methodArgs)
{
if( arg == methodArg) count++;
}
return count;
}
/*
* Method that validate the verification mode used in the verify.
* Not all the methods from the fflib_VerificationMode are implemented for the different classes that extends the fflib_MethodVerifier.
* The error is thrown at run time, so this method is called in the method that actually performs the verify.
* @param verificationMode The verification mode that have to been verified.
* @throws Exception with message for the fflib_VerificationMode not implemented.
*/
protected override void validateMode(fflib_VerificationMode verificationMode)
{
if(verificationMode.Method == fflib_VerificationMode.ModeName.CALLS)
{
throw new fflib_ApexMocks.ApexMocksException(
'The calls() method is available only in the InOrder Verification.');
}
}
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_AnyOrder.cls-meta.xml
================================================
63.0
Active
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_ApexMocks.cls
================================================
/*
Copyright (c) 2014-2017 FinancialForce.com, inc. All rights reserved.
*/
/**
* @group Core
*/
@NamespaceAccessible
public with sharing class fflib_ApexMocks implements System.StubProvider
{
public static final Integer NEVER = 0;
private final fflib_MethodCountRecorder methodCountRecorder;
private final fflib_MethodReturnValueRecorder methodReturnValueRecorder;
private fflib_MethodVerifier methodVerifier;
private fflib_VerificationMode verificationMode;
private fflib_Answer myAnswer;
public Boolean verifying { get; set; }
public Boolean Stubbing
{
get
{
return methodReturnValueRecorder.Stubbing;
}
private set;
}
public List DoThrowWhenExceptions
{
get
{
return methodReturnValueRecorder.DoThrowWhenExceptions;
}
set
{
methodReturnValueRecorder.DoThrowWhenExceptions = value;
}
}
/**
* Construct an ApexMocks instance.
*/
@NamespaceAccessible
public fflib_ApexMocks()
{
this.verifying = false;
this.methodCountRecorder = new fflib_MethodCountRecorder();
this.verificationMode = new fflib_VerificationMode();
this.methodVerifier = new fflib_AnyOrder();
this.methodReturnValueRecorder = new fflib_MethodReturnValueRecorder();
this.methodReturnValueRecorder.Stubbing = false;
}
/**
* Creates mock object of given class or interface.
* @param classToMock class or interface to mock.
* @return mock object.
*/
@NamespaceAccessible
public Object mock(Type classToMock)
{
return Test.createStub(classToMock, this);
}
/**
* Inherited from StubProvider.
* @param stubbedObject The stubbed object.
* @param stubbedMethodName The name of the invoked method.
* @param returnType The return type of the invoked method.
* @param listOfParamTypes A list of the parameter types of the invoked method.
* @param listOfParamNames A list of the parameter names of the invoked method.
* @param listOfArgs The actual argument values passed into this method at runtime.
* @return The stubbed return value. Null by default, unless you prepared one that matches this method and argument values in stubbing.
*/
@NamespaceAccessible
public Object handleMethodCall(Object stubbedObject, String stubbedMethodName, Type returnType,
List listOfParamTypes, List listOfParamNames, List listOfArgs)
{
return mockNonVoidMethod(stubbedObject, stubbedMethodName, listOfParamTypes, listOfArgs);
}
@NamespaceAccessible
public static String extractTypeName(Object mockInstance)
{
return String.valueOf(mockInstance).split(':').get(0);
}
/**
* Verify a method was called on a mock object.
* @param mockInstance The mock object instance.
* @return The mock object instance.
*/
@NamespaceAccessible
public Object verify(Object mockInstance)
{
return verify(mockInstance, this.times(1));
}
/**
* Verify a method was called on a mock object.
* @param mockInstance The mock object instance.
* @param verificationMode Defines the constraints for performing the verification (e.g. the minimum and maximum expected invocation counts).
* @return The mock object instance.
*/
@NamespaceAccessible
public Object verify(Object mockInstance, fflib_VerificationMode verificationMode)
{
this.verifying = true;
this.verificationMode = verificationMode;
return mockInstance;
}
/**
* Verify a method was called on a mock object.
* @param mockInstance The mock object instance.
* @param times The number of times you expect the method to have been called.
* @return The mock object instance.
*/
@NamespaceAccessible
public Object verify(Object mockInstance, Integer times)
{
return verify(mockInstance, this.times(times));
}
/**
* Verfiy a method was called on a mock object.
* @param mockInvocation The invocation on the mock containing information about the method and the arguments.
*/
public void verifyMethodCall(fflib_InvocationOnMock mockInvocation)
{
this.methodVerifier.verifyMethodCall(mockInvocation, verificationMode);
this.methodVerifier = new fflib_AnyOrder();
this.verifying = false;
}
/**
* Tell ApexMocks framework you are about to start stubbing using when() calls.
*/
@NamespaceAccessible
public void startStubbing()
{
methodReturnValueRecorder.Stubbing = true;
}
/**
* Tell ApexMocks framework you are about to stop stubbing using when() calls.
*/
@NamespaceAccessible
public void stopStubbing()
{
methodReturnValueRecorder.Stubbing = false;
}
/**
* Setup when stubbing for a mock object instance.
* @param ignoredRetVal This is the return value from the method called on the mockInstance, and is ignored here since we are about to setup
* the stubbed return value using thenReturn() (see MethodReturnValue class below).
*/
@NamespaceAccessible
public fflib_MethodReturnValue when(Object ignoredRetVal)
{
return methodReturnValueRecorder.MethodReturnValue;
}
/**
* Record a method was called on a mock object.
* @param mockInvocation The invocation on the mock containing information about the method and the arguments.
*/
public void recordMethod(fflib_InvocationOnMock mockInvocation)
{
methodCountRecorder.recordMethod(mockInvocation);
}
/**
* Prepare a stubbed method return value.
* @param mockInvocation The invocation on the mock containing information about the method and the arguments.
* @return The MethodReturnValue instance.
*/
public fflib_MethodReturnValue prepareMethodReturnValue(fflib_InvocationOnMock mockInvocation)
{
return methodReturnValueRecorder.prepareMethodReturnValue(mockInvocation);
}
/**
* Get the method return value for the given method call.
* @param mockInvocation The invocation on the mock containing information about the method and the arguments.
* @return The MethodReturnValue instance.
*/
public fflib_MethodReturnValue getMethodReturnValue(fflib_InvocationOnMock mockInvocation)
{
return methodReturnValueRecorder.getMethodReturnValue(mockInvocation);
}
/**
* Setup exception stubbing for a void method.
* @param e The exception to throw.
* @param mockInstance The mock object instance.
*/
@NamespaceAccessible
public Object doThrowWhen(Exception e, Object mockInstance)
{
methodReturnValueRecorder.prepareDoThrowWhenExceptions(new List{e});
return mockInstance;
}
/**
* Setup exception stubbing for a void method.
* @param exps The list of exceptions to throw.
* @param mockInstance The mock object instance.
*/
@NamespaceAccessible
public Object doThrowWhen(List exps, Object mockInstance)
{
methodReturnValueRecorder.prepareDoThrowWhenExceptions(exps);
return mockInstance;
}
/**
* Setup answer stubbing for a void method.
* @param answer The answer to invoke.
* @param mockInstance The mock object instance.
*/
@NamespaceAccessible
public Object doAnswer(fflib_Answer answer, Object mockInstance)
{
this.myAnswer = answer;
return mockInstance;
}
/**
* Mock a void method. Called by generated mock instance classes, not directly by a developers
* code.
* @param mockInstance The mock object instance.
* @param methodName The method for which to prepare a return value.
* @param methodArgTypes The method argument types for which to prepare a return value.
* @param methodArgValues The method argument values for which to prepare a return value.
*/
public void mockVoidMethod(Object mockInstance, String methodName, List methodArgTypes, List methodArgValues)
{
mockNonVoidMethod(mockInstance, methodName, methodArgTypes, methodArgValues);
}
/**
* Mock a non-void method. Called by generated mock instance classes, not directly by a developers
* code.
* @param mockInstance The mock object instance.
* @param methodName The method for which to prepare a return value.
* @param methodArgTypes The method argument types for which to prepare a return value.
* @param methodArgValues The method argument values for which to prepare a return value.
*/
public Object mockNonVoidMethod(Object mockInstance, String methodName, List methodArgTypes, List methodArgValues)
{
fflib_QualifiedMethod qm = new fflib_QualifiedMethod(extractTypeName(mockInstance), methodName, methodArgTypes, mockInstance);
fflib_MethodArgValues argValues = new fflib_MethodArgValues(methodArgValues);
fflib_InvocationOnMock invocation = new fflib_InvocationOnMock(qm, argValues, mockInstance);
if (this.verifying)
{
verifyMethodCall(invocation);
}
else if (Stubbing)
{
fflib_MethodReturnValue methotReturnValue = prepareMethodReturnValue(invocation);
if(DoThrowWhenExceptions != null)
{
methotReturnValue.thenThrowMulti(DoThrowWhenExceptions);
DoThrowWhenExceptions = null;
return null;
}
if(this.myAnswer != null)
{
methotReturnValue.thenAnswer(this.myAnswer);
this.myAnswer = null;
return null;
}
return null;
}
else
{
recordMethod(invocation);
return returnValue(invocation);
}
return null;
}
/**
* Custom exception class for ApexMocks
*/
@NamespaceAccessible
public class ApexMocksException extends Exception
{
}
private Object returnValue(fflib_InvocationOnMock invocation)
{
fflib_MethodReturnValue methodReturnValue = getMethodReturnValue(invocation);
if (methodReturnValue != null)
{
if(methodReturnValue.Answer == null)
{
throw new fflib_ApexMocks.ApexMocksException(
'The stubbing is not correct, no return values have been set.');
}
Object returnedValue = methodReturnValue.Answer.answer(invocation);
if(returnedValue == null)
{
return null;
}
if (returnedValue instanceof Exception)
{
throw ((Exception) returnedValue);
}
return returnedValue;
}
return null;
}
/**
* Sets how many times the method is expected to be called.
* For InOrder verification we copy Mockito behavior which is as follows;
*
* Consume the specified number of matching invocations, ignoring non-matching invocations in between
* Fail an assert if the very next invocation matches, but additional matches can still exist so long as at least one non-matching invocation exists before them
*
* For example if you had a(); a(); b(); a();
* then inOrder.verify(myMock, 2)).a(); or inOrder.verify(myMock, 3)).a(); would pass but not inOrder.verify(myMock, 1)).a();
* @param times The number of times you expect the method to have been called.
* @return The fflib_VerificationMode object instance with the proper settings.
*/
@NamespaceAccessible
public fflib_VerificationMode times(Integer times)
{
return new fflib_VerificationMode().times(times);
}
/**
* Sets how many times the method is expected to be called for an InOrder verifier. Available Only with the InOrder verification.
* A verification mode using calls will not fail if the method is called more times than expected.
* @param times The number of times you expect the method to have been called in the InOrder verifying ( no greedy verify).
* @return The fflib_VerificationMode object instance with the proper settings.
*/
@NamespaceAccessible
public fflib_VerificationMode calls(Integer times)
{
return new fflib_VerificationMode().calls(times);
}
/**
* Sets a custom assert message for the verify.
* @param customAssertMessage The custom message for the assert in case the assert is false. The custom message is queued to the default message.
* @return The fflib_VerificationMode object instance with the proper settings.
*/
@NamespaceAccessible
public fflib_VerificationMode description(String customAssertMessage)
{
return new fflib_VerificationMode().description(customAssertMessage);
}
/**
* Sets the minimum number of times the method is expected to be called.
* With the InOrder verification it performs a greedy verification, which means it would consume all the instances of the method verified.
* @param atLeastTimes The minimum number of times you expect the method to have been called.
* @return The fflib_VerificationMode object instance with the proper settings.
*/
@NamespaceAccessible
public fflib_VerificationMode atLeast(Integer atLeastTimes)
{
return new fflib_VerificationMode().atLeast(atLeastTimes);
}
/**
* Sets the maximum number of times the method is expected to be called. Not available in the InOrder verification.
* @param atMostTimes The maximum number of times the method is expected to be called.
* @return The fflib_VerificationMode object instance with the proper settings.
*/
@NamespaceAccessible
public fflib_VerificationMode atMost(Integer atMostTimes)
{
return new fflib_VerificationMode().atMost(atMostTimes);
}
/**
* Sets that the method is called at least once.
* With the InOrder verification it performs a greedy verification, which means it would consume all the instances of the method verified.
* @return The fflib_VerificationMode object instance with the proper settings.
*/
@NamespaceAccessible
public fflib_VerificationMode atLeastOnce()
{
return new fflib_VerificationMode().atLeastOnce();
}
/**
* Sets the range of how many times the method is expected to be called. Not available in the InOrder verification.
* @param atLeastTimes The minimum number of times you expect the method to have been called.
* @param atMostTimes The maximum number of times the method is expected to be called.
* @return The fflib_VerificationMode object instance with the proper settings.
*/
@NamespaceAccessible
public fflib_VerificationMode between(Integer atLeastTimes, Integer atMostTimes)
{
return new fflib_VerificationMode().between(atLeastTimes, atMostTimes);
}
/**
* Sets that the method is not expected to be called.
* @return The fflib_VerificationMode object instance with the proper settings.
*/
@NamespaceAccessible
public fflib_VerificationMode never()
{
return new fflib_VerificationMode().never();
}
/**
* Sets the fflib_VerificationMode object.
* To internal use only.
* Used to pass the verification mode that has been set in the verify of the fflib_InOrder class.
* @return The fflib_VerificationMode object instance with the proper settings.
*/
public void setOrderedVerifier(fflib_InOrder verifyOrderingMode)
{
this.methodVerifier = verifyOrderingMode;
}
/**
* A simple override to suppress the default toString logic, which is noisy and rarely useful.
* In some cases, the Salesforce default implementation of toString here can cause internal Salesforce errors
* if it has circular references.
* @return "fflib_ApexMocks" String literal
*/
public override String toString()
{
return 'fflib_ApexMocks';
}
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_ApexMocks.cls-meta.xml
================================================
63.0
Active
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_ApexMocksConfig.cls
================================================
/*
* Copyright (c) 2017 FinancialForce.com, inc. All rights reserved.
*/
@IsTest
@NamespaceAccessible
public class fflib_ApexMocksConfig
{
/**
* When false, stubbed behaviour and invocation counts are shared among all test spies.
* - See fflib_ApexMocksTest.thatMultipleInstancesCanBeMockedDependently
* - This is the default for backwards compatibility.
* When true, each test spy instance has its own stubbed behaviour and invocations.
* - See fflib_ApexMocksTest.thatMultipleInstancesCanBeMockedIndependently
*/
@NamespaceAccessible
public static Boolean HasIndependentMocks {get; set;}
static
{
HasIndependentMocks = false;
}
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_ApexMocksConfig.cls-meta.xml
================================================
63.0
Active
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_ApexMocksUtils.cls
================================================
/**
* Copyright (c) 2014-2016, FinancialForce.com, inc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the FinancialForce.com, inc nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@NamespaceAccessible
public class fflib_ApexMocksUtils
{
/**
* This is taken from https://gist.github.com/afawcett/8dbfc0e1d8c43c982881.
*
* This method works on the principle that serializing and deserialising child records is supported
*
* System.assertEquals(1, ((List)
* JSON.deserialize(
* JSON.serialize(
* [select Id, Name,
* (select Id, Name from Children__r) from Master__c]), List.class))
* [0].Children__r.size());
*
* This method results internally in constructing this JSON, before deserialising it back into SObject's
*
* [
* {
* "attributes": {
* "type": "Master__c",
* "url": "/services/data/v32.0/sobjects/Master__c/a0YG0000005Jn5uMAC"
* },
* "Name": "Fred",
* "Id": "a0YG0000005Jn5uMAC",
* "Children__r": {
* "totalSize": 1,
* "done": true,
* "records": [
* {
* "attributes": {
* "type": "Child__c",
* "url": "/services/data/v32.0/sobjects/Child__c/a0ZG0000006JGPAMA4"
* },
* "Name": "Bob",
* "Id": "a0ZG0000006JGPAMA4",
* "Master__c": "a0YG0000005Jn5uMAC"
* }
* ]
* }
* ]
*/
public static Object makeRelationship(Type parentsType, List parents, SObjectField relationshipField, List> children) {
// Find out more about this relationship...
String relationshipFieldName = relationshipField.getDescribe().getName();
DescribeSObjectResult parentDescribe = parents.getSObjectType().getDescribe();
return deserializeParentsAndChildren(parentsType, parentDescribe, relationshipField, parents, children);
}
/**
* Generic overload to makeRelationship. Enables creation of
* relationships in a loosely-coupled manner.
*/
@NamespaceAccessible
public static Object makeRelationship(
String parentTypeName,
String childTypeName,
List parents,
String relationshipFieldName,
List> children) {
// Find out more about this relationship...
SObjectType parentType = getType(parentTypeName);
SObjectField relationshipField = getField(childTypeName, relationshipFieldName);
DescribeSObjectResult parentDescribe = parentType.getDescribe();
Type parentsType = List.class;
return deserializeParentsAndChildren(parentsType, parentDescribe, relationshipField, parents, children);
}
/**
* Gives the ability to set test values on formula
* and other read-only fields of mock SObjects
*/
@NamespaceAccessible
public static Object setReadOnlyFields(SObject objInstance, Type deserializeType, Map properties) {
Map fieldNameMap = new Map();
for (SObjectField field : properties.keySet()) {
// Resolve the fieldNames from the FieldTokens
fieldNameMap.put(field.getDescribe().getName(), properties.get(field));
}
return (SObject) setReadOnlyFields(objInstance, deserializeType, fieldNameMap);
}
/**
* Generic overload to setReadOnlyFields. Enables setting test
* values on read-only fields by their name
*/
@NamespaceAccessible
public static Object setReadOnlyFields(SObject objInstance, Type deserializeType, Map properties) {
Map mergedMap = new Map(objInstance.getPopulatedFieldsAsMap());
// Merge the values from the properties map into the fields already set on the object
mergedMap.putAll(properties);
// Serialize the merged map, and then deserialize it as the desired object type.
String jsonString = JSON.serializePretty(mergedMap);
return (SObject) JSON.deserialize(jsonString, deserializeType);
}
/**
* Helper Methods
*/
private static Object deserializeParentsAndChildren(
Type parentsType,
DescribeSObjectResult parentDescribe,
SObjectField relationshipField,
List parents,
List> children
) {
List childRelationships = parentDescribe.getChildRelationships();
String relationshipName = null;
for(Schema.ChildRelationship childRelationship : childRelationships) {
if(childRelationship.getField() == relationshipField) {
relationshipName = childRelationship.getRelationshipName();
break;
}
}
// Stream the parsed JSON representation of the parent objects back out, injecting children as it goes
JSONParser parentsParser = JSON.createParser(JSON.serialize(parents));
JSONParser childrenParser = JSON.createParser(JSON.serialize(children));
JSONGenerator combinedOutput = JSON.createGenerator(false);
streamTokens(parentsParser, combinedOutput, new InjectChildrenEventHandler(childrenParser, relationshipName, children) );
// Derserialise back into SObject list complete with children
return JSON.deserialize(combinedOutput.getAsString(), parentsType);
}
/**
* Monitors stream events for end of object for each SObject contained in the parent list
* then injects the respective childs record list into the stream
*/
private class InjectChildrenEventHandler implements JSONParserEvents
{
private JSONParser childrenParser;
private String relationshipName;
private List> children;
private Integer childListIdx = 0;
public InjectChildrenEventHandler(JSONParser childrenParser, String relationshipName, List> children) {
this.childrenParser = childrenParser;
this.relationshipName = relationshipName;
this.children = children;
this.childrenParser.nextToken(); // Consume the outer array token
}
public void nextToken(JSONParser fromStream, Integer depth, JSONGenerator toStream) {
// Inject children?
JSONToken currentToken = fromStream.getCurrentToken();
if(depth == 2 && currentToken == JSONToken.END_OBJECT ) {
toStream.writeFieldName(relationshipName);
toStream.writeStartObject();
toStream.writeNumberField('totalSize', children[childListIdx].size());
toStream.writeBooleanField('done', true);
toStream.writeFieldName('records');
streamTokens(childrenParser, toStream, null);
toStream.writeEndObject();
childListIdx++;
}
}
}
/**
* Utility function to stream tokens from a reader to a write, while providing a basic eventing model
*/
private static void streamTokens(JSONParser fromStream, JSONGenerator toStream, JSONParserEvents events)
{
Integer depth = 0;
while (fromStream.nextToken() != null)
{
// Give event handler chance to inject
if (events != null) {
events.nextToken(fromStream, depth, toStream);
}
// Forward to output stream
switch on fromStream.getCurrentToken() {
when START_ARRAY {
toStream.writeStartArray();
depth++;
}
when START_OBJECT {
toStream.writeStartObject();
depth++;
}
when FIELD_NAME {
toStream.writeFieldName(fromStream.getCurrentName());
}
when VALUE_STRING, VALUE_FALSE, VALUE_TRUE, VALUE_NUMBER_FLOAT, VALUE_NUMBER_INT {
toStream.writeString(fromStream.getText());
}
when VALUE_NULL {
toStream.writeNull();
}
when END_OBJECT {
toStream.writeEndObject();
depth--;
}
when END_ARRAY {
toStream.writeEndArray();
depth--;
}
}
// Don't continue to stream beyond the initial starting point
if (depth == 0)
break;
}
}
/**
* Basic event used during the above streaming
*/
private interface JSONParserEvents
{
void nextToken(JSONParser fromStream, Integer depth, JSONGenerator toStream);
}
/**
* Gets the SObjectType by name
*/
private static Schema.SObjectType getType(String typeName) {
Map gd = Schema.getGlobalDescribe();
SObjectType sobjType = gd.get(typeName);
if (sobjType == null) {
throw new fflib_ApexMocks.ApexMocksException('SObject type not found: ' + typeName);
}
return sobjType;
}
/**
* Gets the SObjectField of an object by name
*/
private static Schema.SObjectField getField(String objectName, String fieldName) {
SObjectType sobjType = getType(objectName);
Map objectFields = sobjType.getDescribe().fields.getMap();
Schema.SObjectField sobjField = objectFields.get(fieldName);
if (sobjField == null) {
throw new fflib_ApexMocks.ApexMocksException('SObject field not found: ' + fieldName);
}
return sobjField;
}
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_ApexMocksUtils.cls-meta.xml
================================================
63.0
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_ArgumentCaptor.cls
================================================
/*
* Copyright (c) 2016, FinancialForce.com, inc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the FinancialForce.com, inc nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This class implements the capturing framework for ApexMocks
* According to Mockito's syntax the type is passed in the capturer construction,
* however Apex cannot perform the auto casting that Java can.
* To be consistent with Mockito, the capturer does not perform any checks on the type of the argument.
* @group Core
*/
@NamespaceAccessible
public with sharing class fflib_ArgumentCaptor
{
protected List argumentsCaptured = new List();
/**
* Factory method to create a new fflib_ArgumentCaptor.
* Takes the captured argument's Type for consistency with Mockito syntax.
* The Type is IGNORED because we can't determine an object instance's Type at runtime unlike in Java.
* Rigorous type checking may be introduced in a future release, so you should specify the expected argument type correctly.
*
* @param ignoredCaptureType Type (class) of the captured argument
* @return A new fflib_ArgumentCaptor.
*/
@NamespaceAccessible
public static fflib_ArgumentCaptor forClass(Type ignoredCaptureType)
{
return new fflib_ArgumentCaptor();
}
/**
* Use it to capture the argument. This method must be used inside verification.
* Internally, this method registers a special implementation of a Matcher.
* This argument matcher stores the argument value so that you can use it later to perform assertions.
*
* @return a special matcher that matches any argument and remembers the value.
*/
@NamespaceAccessible
public Object capture()
{
AnyObject myMatcher = new AnyObject(this);
return fflib_Match.matches(myMatcher);
}
/**
* Returns the captured value of the argument. When capturing all arguments use getAllValues().
* If verified method was called multiple times then this method returns the latest captured value.
*
* @return captured argument value.
*/
@NamespaceAccessible
public Object getValue()
{
if( argumentsCaptured == null ||
argumentsCaptured.size() == 0)
{
return null;
}
//returns the last argument called
return argumentsCaptured.get( argumentsCaptured.size() - 1 );
}
/**
* Returns all captured values. Use it when capturing multiple arguments or when the verified method was called multiple times.
* When capturing multiple arguments is called multiple times, this method returns a merged list of all values from all invocations.
*
* @return Returns all captured values. Use it when capturing multiple arguments on the same call or when the verified method was called multiple times.
*/
@NamespaceAccessible
public List getAllValues()
{
return argumentsCaptured;
}
@NamespaceAccessible
public class AnyObject implements fflib_IMatcher
{
private fflib_ArgumentCaptor captor;
private Object value;
public AnyObject(fflib_ArgumentCaptor captor)
{
this.captor = captor;
}
//match with all the possible values and store the arg value
public Boolean matches(Object arg)
{
value = arg;
return true;
}
//store the argument in the list ( this would be called inside the method counter where is compared with the matchers of the method)
public void storeArgument()
{
captor.argumentsCaptured.add(value);
}
}
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_ArgumentCaptor.cls-meta.xml
================================================
63.0
Active
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_IDGenerator.cls
================================================
/**
* Copyright (c) 2014, FinancialForce.com, inc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the FinancialForce.com, inc nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@NamespaceAccessible
public with sharing class fflib_IDGenerator
{
private static Integer fakeIdCount = 0;
private static final String ID_PATTERN = '000000000000';
/**
* Generate a fake Salesforce Id for the given SObjectType
*/
@NamespaceAccessible
public static Id generate(Schema.SObjectType sobjectType)
{
String keyPrefix = sobjectType.getDescribe().getKeyPrefix();
fakeIdCount++;
String fakeIdPrefix = ID_PATTERN.substring(0, ID_PATTERN.length() - String.valueOf(fakeIdCount).length());
return Id.valueOf(keyPrefix + fakeIdPrefix + fakeIdCount);
}
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_IDGenerator.cls-meta.xml
================================================
63.0
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_IMatcher.cls
================================================
/**
* Copyright (c) 2014-2016, FinancialForce.com, inc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the FinancialForce.com, inc nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@NamespaceAccessible
public interface fflib_IMatcher
{
/**
* Whether or not the supplied argument is a match.
* Any supplementary information (e.g. boundary conditions, objects to match to etc)
* should be cached by the matcher constructor.
* @param arg The argument value supplied to the method
* @return Boolean True if the argument value is a match, false otherwise.
*/
Boolean matches(Object arg);
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_IMatcher.cls-meta.xml
================================================
63.0
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_InOrder.cls
================================================
/*
Copyright (c) 2017 FinancialForce.com, inc. All rights reserved.
*/
/**
* @group Core
*/
@NamespaceAccessible
public with sharing class fflib_InOrder extends fflib_MethodVerifier
{
private final List unorderedMockInstances;
private Integer idxMethodCall = 0;
private Set notImplementedMethods =
new Set
{
fflib_VerificationMode.ModeName.atMost,
fflib_VerificationMode.ModeName.between
};
private final fflib_ApexMocks mocks;
/**
* Construct the InOrder instance.
* @param mocks The apex mock object instance.
* @param unorderedMockInstances One or more mock implementation classes (listed in any order), whose ordered method calls require verification.
*/
@NamespaceAccessible
public fflib_InOrder(fflib_ApexMocks mocks, List unorderedMockInstances)
{
this.unorderedMockInstances = unorderedMockInstances;
this.mocks = mocks;
}
/**
* Verify a method was called on a mock object.
* It performs a no strict ordered verification.
* The verification could be either greedy or not depending of the verificationMode passed.
* Check the fflib_VerificationMode methods for details.
* @param mockInstance The mock object instance.
* @param verificationMode Defines the constraints for performing the verification (e.g. the minimum and maximum expected invocation counts).
* @return The mock object instance.
*/
@NamespaceAccessible
public Object verify(Object mockInstance, fflib_VerificationMode verificationMode)
{
mocks.setOrderedVerifier(this);
return mocks.verify(mockInstance, verificationMode);
}
/**
* Verify a method was called on a mock object.
* It performs the default times(1) verification for the InOrder.
* @param mockInstance The mock object instance.
* @return The mock object instance.
*/
@NamespaceAccessible
public Object verify(Object mockInstance)
{
mocks.setOrderedVerifier(this);
return mocks.verify(mockInstance);
}
/**
* Verify a method was called on a mock object.
* Wrapper for the new syntax call to be conformed to the old style notation
* It performs the equivalent of times(times) verification for the InOrder.
* @param mockInstance The mock object instance.
* @param times The number of times you expect the method to have been called.
* @return The mock object instance.
*/
@NamespaceAccessible
public Object verify(Object mockInstance, Integer times)
{
mocks.setOrderedVerifier(this);
return mocks.verify(mockInstance, times);
}
/**
* Verify that after the last successful verified method no more interactions happened on the inOrderMock instance.
* @throws Exception with message to help to identify the last method called.
*/
@NamespaceAccessible
public void verifyNoMoreInteractions()
{
if(idxMethodCall == 0)
{
verifyNoInteractions();
}
if(hasNextInteraction(unorderedMockInstances, idxMethodCall))
{
fflib_InvocationOnMock invocation =
fflib_MethodCountRecorder.getOrderedMethodCalls().get(idxMethodCall -1);
throw new fflib_ApexMocks.ApexMocksException(
'No more Interactions were expected after the ' + invocation.getMethod() +' method.');
}
}
/**
* Verify that no interactions at all happened on the inOrderMock instance.
* @throws Exception with message.
*/
@NamespaceAccessible
public void verifyNoInteractions()
{
if(hasNextInteraction(unorderedMockInstances, 0))
{
throw new fflib_ApexMocks.ApexMocksException(
'No Interactions expected on this InOrder Mock instance!');
}
}
/*
* Verifies a method was invoked the expected number of times, with the expected arguments.
* The in-order verifier remembers the last method invocation it successfully verified,
* and only considers subsequent method invocations for subsequent verifications.
* @param qualifiedMethod The method to be verified.
* @param expectedArguments The arguments of the method that needs to be verified.
* @param verificationMode The verification mode that holds the setting about how the verification should be performed.
*/
protected override void verify(
fflib_QualifiedMethod qm,
fflib_MethodArgValues expectedArguments,
fflib_VerificationMode verificationMode)
{
String inOrder = ' in order';
List matchers = fflib_Match.Matching ? fflib_Match.getAndClearMatchers(expectedArguments.argValues.size()) : null;
List actualInvocations = fflib_MethodCountRecorder.getOrderedMethodCalls();
List actualArguments = new List();
for (fflib_InvocationOnMock invocation : actualInvocations)
{
actualArguments.add(invocation.getMethodArgValues());
}
if( verificationMode.VerifyMin == 0 && verificationMode.VerifyMax == 0)
{
Integer methodCounts = countInteractions(matchers, qm, expectedArguments);
if(methodCounts != 0 )
throwException(qm, inOrder, fflib_ApexMocks.NEVER, '', methodCounts, verificationMode.CustomAssertMessage, expectedArguments, matchers, actualArguments);
}
Integer i=0;
for ( ; i matchers,
fflib_QualifiedMethod qm,
fflib_MethodArgValues methodArg)
{
fflib_InvocationOnMock calledMethod = getNextMethodCall();
while(calledMethod != null)
{
if(calledMethod.getMethod() == qm &&
argumentsMatch(calledMethod.getMethodArgValues(), matchers, methodArg))
{
//it's our method
if (matchers != null)
{
capture(matchers);
}
return true;
}
calledMethod = getNextMethodCall();
}
return false;
}
private Integer countInteractions(
List matchers,
fflib_QualifiedMethod qualifiedMethod,
fflib_MethodArgValues methodArg)
{
Integer interactionsCouter = 0;
for (Integer i = idxMethodCall, len = fflib_MethodCountRecorder.getOrderedMethodCalls().size(); i matchers,
fflib_QualifiedMethod qualifiedMethod,
fflib_MethodArgValues methodArg)
{
Integer lastInteracionIndex = 0;
//going all through the orderedMethodCalls to find all the interaction of the method
for (Integer i = idxMethodCall, len = fflib_MethodCountRecorder.getOrderedMethodCalls().size(); i matchers,
fflib_MethodArgValues methodArg)
{
//Check it was called with the right args.
if (matchers != null)
{
if(fflib_Match.matchesAllArgs(calledMethodArg, matchers))
{
//Return now we've matched the method call
return true;
}
}
else if(calledMethodArg == methodArg)
{
//Return now we've matched the method call
return true;
}
return false;
}
private fflib_InvocationOnMock getNextMethodCall()
{
return getNextMethodCall(true);
}
private fflib_InvocationOnMock getNextMethodCall(Boolean updateIdxMethodCall)
{
Integer idx = 0;
for (fflib_InvocationOnMock invocation : fflib_MethodCountRecorder.getOrderedMethodCalls())
{
if (idx == idxMethodCall)
{
if(isForMockInstance(invocation))
{
if(updateIdxMethodCall)
idxMethodCall++;
return invocation;
}
}
else
{
idx++;
}
}
return null;
}
private Boolean isForMockInstance(fflib_InvocationOnMock invocation)
{
for (Object mi : unorderedMockInstances)
{
if (mi === invocation.getMock())
{
return true;
}
}
return false;
}
/*
* Used by the fflib_InOrder invocation verifier to find further interactions with a given mock instances.
* @param mockInstances The tracked mock instances - only methods called on these objects are counted as an invocation.
* @param idxLastMethodCalled The index of the last matched method, used to offset the search for invocations so we don't double count invocations.
* @return Whether or not there were further interactions.
*/
private Boolean hasNextInteraction(List mockInstances, Integer idxLastMethodCalled)
{
Integer idx = 0;
for (fflib_InvocationOnMock methodCall : fflib_MethodCountRecorder.getOrderedMethodCalls())
{
if (isForMockInstance(methodCall))
{
idx++;
if (idx > idxLastMethodCalled)
{
return true;
}
}
}
return false;
}
/*
* Method that validate the verification mode used in the verify.
* Not all the methods from the fflib_VerificationMode are implemented for the different classes that extends the fflib_MethodVerifier.
* The error is thrown at run time, so this method is called in the method that actually performs the verify.
* @param verificationMode The verification mode that have to been verified.
* @throws Exception with message for the fflib_VerificationMode not implemented.
*/
protected override void validateMode(fflib_VerificationMode verificationMode)
{
if(notImplementedMethods.contains(verificationMode.Method))
{
throw new fflib_ApexMocks.ApexMocksException(
'The ' + verificationMode.Method.name() + ' method is not implemented for the fflib_InOrder class');
}
}
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_InOrder.cls-meta.xml
================================================
63.0
Active
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_Inheritor.cls
================================================
/*
* Copyright (c) 2016-2017 FinancialForce.com, inc. All rights reserved.
*/
@isTest
@NamespaceAccessible
public class fflib_Inheritor implements IA, IB, IC
{
public interface IA {String doA();}
public interface IB {String doB();}
public interface IC {String doC();}
public String doA(){return 'Did A';}
public String doB(){return 'Did B';}
public String doC(){return 'Did C';}
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_Inheritor.cls-meta.xml
================================================
63.0
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_InvocationOnMock.cls
================================================
/*
Copyright (c) 2017 FinancialForce.com, inc. All rights reserved.
*/
/**
* An invocation on a mock.
* A place holder for mock, the method that was called and the arguments that were passed.
* @group Core
*/
@NamespaceAccessible
public with sharing class fflib_InvocationOnMock
{
private fflib_QualifiedMethod qm;
private fflib_MethodArgValues methodArg;
private Object mockInstance;
/**
* Constructor for the class.
* @param qm The fflib_QualifiedMethod instance to be stored.
* @param args The fflib_MethodArgValues instance to be stored.
* @param mockInstance The mock instance to be stored.
*/
@NamespaceAccessible
public fflib_InvocationOnMock(fflib_QualifiedMethod qm, fflib_MethodArgValues args, Object mockInstance)
{
this.qm = qm;
this.methodArg = args;
this.mockInstance = mockInstance;
}
/**
* Returns the argument at the given index.
* @param index The index of the wanted argument.
* @throws ApexMocksException in case the index is out of range.
* @return The argument at the given index.
*/
@NamespaceAccessible
public Object getArgument(Integer index)
{
validateIndex(index);
return methodArg.argValues[index];
}
/**
* Returns the list of arguments passed to the method.
* @return The list of arguments.
*/
@NamespaceAccessible
public List getArguments()
{
return methodArg.argValues;
}
/**
* Returns fflib_MethodArgValues instance that represents the arguments passed to the method.
* @return The fflib_MethodArgValues instance that represents the arguments passed to the method.
*/
@NamespaceAccessible
public fflib_MethodArgValues getMethodArgValues()
{
return methodArg;
}
/**
* Returns the fflib_QualifiedMethod instance that represent the fully qualified method called within the invocation.
* @return The method stored in the invocation.
*/
@NamespaceAccessible
public fflib_QualifiedMethod getMethod()
{
return qm;
}
/**
* Returns the mock object on which the invocation occurs.
* @return The mock object on which the invocation occurs.
*/
@NamespaceAccessible
public Object getMock()
{
return mockInstance;
}
private void validateIndex(Integer index)
{
if(index < 0 || index >= methodArg.argValues.size())
{
throw new fflib_ApexMocks.ApexMocksException('Invalid index, must be greater or equal to zero and less of ' + methodArg.argValues.size()+'.');
}
}
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_InvocationOnMock.cls-meta.xml
================================================
63.0
Active
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_Match.cls
================================================
/**
* Copyright (c) 2014, FinancialForce.com, inc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the FinancialForce.com, inc nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@NamespaceAccessible
public class fflib_Match
{
private static List matchers = new List();
/**
* Matching
* True when comparing method arg values to matchers, false when comparing absolute arg values.
*/
public static Boolean Matching = false;
/**
* Used internally by the mocking framework, you shouldn't need to call this method directly.
* Copies the registered matchers, and then switches matching mode off.
* @param expectedSize The expected number of matchers to be returned. If this does not match the actual value an expection is thrown.
* @return List The registered matchers, collected while in matching mode.
*/
@NamespaceAccessible
public static List getAndClearMatchers(Integer expectedSize)
{
Matching = false;
List retval = matchers.clone();
matchers.clear();
if (retval.size() != expectedSize)
{
throw new fflib_ApexMocks.ApexMocksException('The number of matchers defined (' + retval.size() + ').'
+ ' does not match the number expected (' + expectedSize + ')\n'
+ 'If you are using matchers all arguments must be passed in as matchers.\n'
+ 'For example myList.add(fflib_Match.anyInteger(), \'String\') should be defined as myList.add(fflib_Match.anyInteger(), fflib_Match.eq(\'String\')).');
}
return retval;
}
/**
* Used internally by the mocking framework, you shouldn't need to call this method directly.
* Compares all supplied method arg values to the supplied target matchers.
* @param methodArg The arguments supplied when the method was called
* @param targetMatchers The matchers the arguments need to be compared with
* @throws fflib_ApexMocks.ApexMocksException Thrown when methodArgValues is null/empty, targetMatchers is null, or their sizes don't match
* @return Boolean True if all arg values satisfy all of the supplied matchers.
*/
@NamespaceAccessible
public static Boolean matchesAllArgs(fflib_MethodArgValues methodArg, List targetMatchers)
{
validateArgs(methodArg, targetMatchers);
Integer matchersSize = targetMatchers.size();
for (Integer i=0; i targetMatchers)
{
if (methodArg == null)
{
throw new fflib_ApexMocks.ApexMocksException('MethodArgs cannot be null');
}
if (methodArg.argValues == null)
{
throw new fflib_ApexMocks.ApexMocksException('MethodArgs.argValues cannot be null');
}
if (targetMatchers == null)
{
throw new fflib_ApexMocks.ApexMocksException('Matchers cannot be null');
}
if (targetMatchers.size() != methodArg.argValues.size())
{
throw new fflib_ApexMocks.ApexMocksException('MethodArgs and matchers must have the same count'
+ ', MethodArgs: (' + methodArg.argValues.size() + ') ' + methodArg.argValues
+ ', Matchers: (' + targetMatchers.size() + ') ' + targetMatchers);
}
}
/**
* Registers a matcher which will be stubbed/verified against.
* @param matcher The matcher that needs to be compared
* @return Object Always returns null. This can then be cast into the correct arg type
* so that the right method is called on the mock objects.
*/
@NamespaceAccessible
public static Object matches(fflib_IMatcher matcher)
{
Matching = true;
matchers.add(matcher);
return null;
}
/**
* COMBINED MATCHER
* The allOf, anyOf and noneOf methods are overloaded to provide fluent matcher calls for up to 4 matcher conditions.
* To connect 5 or more, the List version directly.
*/
/**
* Registers a matcher which will check if the method is called with an arg that matches allOf
* @param o1 A dummy object returned by registering another matcher
* @param o2 A dummy object returned by registering another matcher
* @return Object A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked. (You may need to cast down to your specific object type)public static Object allOf(Object o1, Object o2)
*/
public static Object allOf(Object o1, Object o2)
{
return allOf(new Object[]{ o1, o2 });
}
/**
* Registers a matcher which will check if the method is called with an arg that matches allOf
* @param o1 A dummy object returned by registering another matcher
* @param o2 A dummy object returned by registering another matcher
* @param o3 A dummy object returned by registering another matcher
* @return Object A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked. (You may need to cast down to your specific object type)
*/
public static Object allOf(Object o1, Object o2, Object o3)
{
return allOf(new Object[]{ o1, o2, o3 });
}
/**
* Registers a matcher which will check if the method is called with an arg that matches allOf
* @param o1 A dummy object returned by registering another matcher
* @param o2 A dummy object returned by registering another matcher
* @param o3 A dummy object returned by registering another matcher
* @param o4 A dummy object returned by registering another matcher
* @return Object A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked. (You may need to cast down to your specific object type)
*/
public static Object allOf(Object o1, Object o2, Object o3, Object o4)
{
return allOf(new Object[]{ o1, o2, o3, o4 });
}
/**
* Registers a matcher which will check if the method is called with an arg that matches allOf
* @param o A list of dummy objects returned by registering other matchers
* @return Object A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked. (You may need to cast down to your specific object type)
*/
public static Object allOf(List o)
{
return combined(fflib_MatcherDefinitions.Connective.ALL, o);
}
/**
* Registers a matcher which will check if the method is called with an arg that matches anyOf
* @param o1 A dummy object returned by registering another matcher
* @param o2 A dummy object returned by registering another matcher
* @return Object A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked. (You may need to cast down to your specific object type)
*/
public static Object anyOf(Object o1, Object o2)
{
return anyOf(new Object[]{ o1, o2 });
}
/**
* Registers a matcher which will check if the method is called with an arg that matches anyOf
* @param o1 A dummy object returned by registering another matcher
* @param o2 A dummy object returned by registering another matcher
* @param o3 A dummy object returned by registering another matcher
* @return Object A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked. (You may need to cast down to your specific object type)
*/
public static Object anyOf(Object o1, Object o2, Object o3)
{
return anyOf(new Object[]{ o1, o2, o3 });
}
/**
* Registers a matcher which will check if the method is called with an arg that matches anyOf
* @param o1 A dummy object returned by registering another matcher
* @param o2 A dummy object returned by registering another matcher
* @param o3 A dummy object returned by registering another matcher
* @param o4 A dummy object returned by registering another matcher
* @return Object A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked. (You may need to cast down to your specific object type)
*/
public static Object anyOf(Object o1, Object o2, Object o3, Object o4)
{
return anyOf(new Object[]{ o1, o2, o3, o4 });
}
/**
* Registers a matcher which will check if the method is called with an arg that matches anyOf
* @param o A list of dummy objects returned by registering other matchers
* @return Object A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked. (You may need to cast down to your specific object type)
*/
public static Object anyOf(List o)
{
return combined(fflib_MatcherDefinitions.Connective.AT_LEAST_ONE, o);
}
/**
* Registers a matcher which will check if the method is called with an arg that matches isNot
* @param o1 A dummy object returned by registering another matcher
* @return Object A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked. (You may need to cast down to your specific object type)
*/
public static Object isNot(Object o1)
{
return noneOf(new Object[]{ o1 });
}
/**
* Registers a matcher which will check if the method is called with an arg that matches noneOf
* @param o1 A dummy object returned by registering another matcher
* @param o2 A dummy object returned by registering another matcher
* @return Object A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked. (You may need to cast down to your specific object type)
*/
public static Object noneOf(Object o1, Object o2)
{
return noneOf(new Object[]{ o1, o2 });
}
/**
* Registers a matcher which will check if the method is called with an arg that matches noneOf
* @param o1 A dummy object returned by registering another matcher
* @param o2 A dummy object returned by registering another matcher
* @param o3 A dummy object returned by registering another matcher
* @return Object A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked. (You may need to cast down to your specific object type)
*/
public static Object noneOf(Object o1, Object o2, Object o3)
{
return noneOf(new Object[]{ o1, o2, o3 });
}
/**
* Registers a matcher which will check if the method is called with an arg that matches noneOf
* @param o1 A dummy object returned by registering another matcher
* @param o2 A dummy object returned by registering another matcher
* @param o3 A dummy object returned by registering another matcher
* @param o4 A dummy object returned by registering another matcher
* @return Object A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked. (You may need to cast down to your specific object type)
*/
public static Object noneOf(Object o1, Object o2, Object o3, Object o4)
{
return noneOf(new Object[]{ o1, o2, o3, o4 });
}
/**
* Registers a matcher which will check if the method is called with an arg that matches noneOf
* @param o A list of dummy objects returned by registering other matchers
* @return Object A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked. (You may need to cast down to your specific object type)
*/
public static Object noneOf(List o)
{
return combined(fflib_MatcherDefinitions.Connective.NONE, o);
}
private static Object combined(fflib_MatcherDefinitions.Connective connectiveExpression, List o)
{
return matches(new fflib_MatcherDefinitions.Combined(connectiveExpression, (gatherMatchers(o))));
}
private static List gatherMatchers(Object[] ignoredMatcherObjects)
{
if (ignoredMatcherObjects == null || ignoredMatcherObjects.isEmpty())
{
throw new fflib_ApexMocks.ApexMocksException('Must register matchers to combine');
}
//Each ignored matcher object represents a matcher that has been registered against fflib_Match.matchers,
//but is actually for the connective matchers.
List innerMatchers = new List();
Integer innerMatcherCount = ignoredMatcherObjects.size();
while (innerMatchers.size() < innerMatcherCount)
{
if (matchers.isEmpty())
{
throw new fflib_ApexMocks.ApexMocksException('Error reclaiming inner matchers for combined matcher. Wanted '
+ innerMatcherCount + ' matchers but only got ' + innerMatchers);
}
fflib_IMatcher innerMatcher = matchers.remove(matchers.size()-1);
//Add to the start of the list to preserve the order in which matchers were declared.
//Note. Apex throws list index out of bounds if inserting an element into an empty list at index 0S
if (!innerMatchers.isEmpty())
{
innerMatchers.add(0, innerMatcher);
}
else
{
innerMatchers.add(innerMatcher);
}
}
return innerMatchers;
}
/**
* ALL OTHER MATCHER METHODS
*/
/**
* Registers a matcher which will check if the method is called with an arg that matches eq
* @param toMatch The Object to be compared
* @return Object A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked. (You may need to cast down to your specific object type)
*/
public static Object eq(Object toMatch)
{
return matches(new fflib_MatcherDefinitions.Eq(toMatch));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches eqBoolean
* @param toMatch The Boolean to be compared
* @return Boolean A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Boolean eqBoolean(Boolean toMatch)
{
return (Boolean)matches(new fflib_MatcherDefinitions.Eq(toMatch));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches eqDate
* @param toMatch The Date to be compared
* @return Date A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Date eqDate(Date toMatch)
{
return (Date)matches(new fflib_MatcherDefinitions.Eq(toMatch));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches eqDatetime
* @param toMatch The Datetime to be compared
* @return Datetime A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Datetime eqDatetime(Datetime toMatch)
{
return (Datetime)matches(new fflib_MatcherDefinitions.Eq(toMatch));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches eqDecimal
* @param toMatch The Decimal to be compared
* @return Decimal A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Decimal eqDecimal(Decimal toMatch)
{
return (Decimal)matches(new fflib_MatcherDefinitions.Eq(toMatch));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches eqDouble
* @param toMatch The Double to be compared
* @return Double A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Double eqDouble(Double toMatch)
{
return (Double)matches(new fflib_MatcherDefinitions.Eq(toMatch));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches eqId
* @param toMatch The Id to be compared
* @return Id A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Id eqId(Id toMatch)
{
return (Id)matches(new fflib_MatcherDefinitions.Eq(toMatch));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches eqInteger
* @param toMatch The Integer to be compared
* @return Integer A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Integer eqInteger(Integer toMatch)
{
return (Integer)matches(new fflib_MatcherDefinitions.Eq(toMatch));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches eqList
* @param toMatch The List to be compared
* @return List A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static List eqList(List toMatch)
{
return (List)matches(new fflib_MatcherDefinitions.Eq(toMatch));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches eqLong
* @param toMatch The Long to be compared
* @return Long A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Long eqLong(Long toMatch)
{
return (Long)matches(new fflib_MatcherDefinitions.Eq(toMatch));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches eqSObjectField
* @param toMatch The SObjectField to be compared
* @return SObjectField A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static SObjectField eqSObjectField(SObjectField toMatch)
{
return (SObjectField)matches(new fflib_MatcherDefinitions.Eq(toMatch));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches eqSObjectType
* @param toMatch The SObjectType to be compared
* @return SObjectType A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static SObjectType eqSObjectType(SObjectType toMatch)
{
return (SObjectType)matches(new fflib_MatcherDefinitions.Eq(toMatch));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches eqString
* @param toMatch The String to be compared
* @return String A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static String eqString(String toMatch)
{
return (String)matches(new fflib_MatcherDefinitions.Eq(toMatch));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches refEq
* @param toMatch The Object to be compared
* @return Object A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked. (You may need to cast down to your specific object type)
*/
public static Object refEq(Object toMatch)
{
return matches(new fflib_MatcherDefinitions.RefEq(toMatch));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches anyBoolean
* @return Boolean A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Boolean anyBoolean()
{
return (Boolean)matches(new fflib_MatcherDefinitions.AnyBoolean());
}
/**
* Registers a matcher which will check if the method is called with an arg that matches anyDate
* @return Date A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Date anyDate()
{
return (Date)matches(new fflib_MatcherDefinitions.AnyDate());
}
/**
* Registers a matcher which will check if the method is called with an arg that matches anyDatetime
* @return Datetime A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Datetime anyDatetime()
{
return (Datetime)matches(new fflib_MatcherDefinitions.AnyDatetime());
}
/**
* Registers a matcher which will check if the method is called with an arg that matches anyDecimal
* @return Decimal A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Decimal anyDecimal()
{
return (Decimal)matches(new fflib_MatcherDefinitions.AnyDecimal());
}
/**
* Registers a matcher which will check if the method is called with an arg that matches anyDouble
* @return Double A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Double anyDouble()
{
return (Double)matches(new fflib_MatcherDefinitions.AnyDouble());
}
/**
* Registers a matcher which will check if the method is called with an arg that matches anyFieldSet
* @return Schema.FieldSet A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Schema.FieldSet anyFieldSet()
{
return (Schema.FieldSet)matches(new fflib_MatcherDefinitions.AnyFieldSet());
}
/**
* Registers a matcher which will check if the method is called with an arg that matches anyId
* @return Id A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Id anyId()
{
return (Id)matches(new fflib_MatcherDefinitions.AnyId());
}
/**
* Registers a matcher which will check if the method is called with an arg that matches anyInteger
* @return Integer A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Integer anyInteger()
{
return (Integer)matches(new fflib_MatcherDefinitions.AnyInteger());
}
/**
* Registers a matcher which will check if the method is called with an arg that matches anyList
* @return List A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static List anyList()
{
return (List)matches(new fflib_MatcherDefinitions.AnyList());
}
/**
* Registers a matcher which will check if the method is called with an arg that matches anyLong
* @return Long A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Long anyLong()
{
return (Long)matches(new fflib_MatcherDefinitions.AnyLong());
}
/**
* Registers a matcher which will check if the method is called with an arg that matches anyObject
* @return Object A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked. (You may need to cast down to your specific object type)
*/
public static Object anyObject()
{
return matches(new fflib_MatcherDefinitions.AnyObject());
}
/**
* Registers a matcher which will check if the method is called with an arg that matches anyString
* @return String A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static String anyString()
{
return (String)matches(new fflib_MatcherDefinitions.AnyString());
}
/**
* Registers a matcher which will check if the method is called with an arg that matches anySObject
* @return SObject A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static SObject anySObject()
{
return (SObject)matches(new fflib_MatcherDefinitions.AnySObject());
}
/**
* Registers a matcher which will check if the method is called with an arg that matches anySObjectField
* @return SObjectField A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static SObjectField anySObjectField()
{
return (SObjectField)matches(new fflib_MatcherDefinitions.AnySObjectField());
}
/**
* Registers a matcher which will check if the method is called with an arg that matches anySObjectType
* @return SObjectType A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static SObjectType anySObjectType()
{
return (SObjectType)matches(new fflib_MatcherDefinitions.AnySObjectType());
}
/**
* Registers a matcher which will check if the method is called with an arg that matches dateAfter (not inclusive)
* @param fromDate The Date to be compared
* @return Date A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Date dateAfter(Date fromDate)
{
return dateAfter(fromDate, false);
}
/**
* Registers a matcher which will check if the method is called with an arg that matches dateAfter
* @param fromDate The Date to be compared
* @param inclusive Whether or not a Date equal to fromDate should be considered a match
* @return Date A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Date dateAfter(Date fromDate, Boolean inclusive)
{
return (Date)matches(new fflib_MatcherDefinitions.DatetimeAfter(fromDate, inclusive));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches dateBefore (not inclusive)
* @param toDate The Date to be compared
* @return Date A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Date dateBefore(Date toDate)
{
return dateBefore(toDate, false);
}
/**
* Registers a matcher which will check if the method is called with an arg that matches dateBefore
* @param toDate The Date to be compared
* @param inclusive Whether or not a Date equal to toDate should be considered a match
* @return Date A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Date dateBefore(Date toDate, Boolean inclusive)
{
return (Date)matches(new fflib_MatcherDefinitions.DatetimeBefore(toDate, inclusive));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches dateBetween (not inclusive)
* @param fromDate The lower bound Date to be compared
* @param toDate The upper bound Date to be compared
* @return Date A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Date dateBetween(Date fromDate, Date toDate)
{
return dateBetween(fromDate, false, toDate, false);
}
/**
* Registers a matcher which will check if the method is called with an arg that matches dateBetween
* @param fromDate The lower bound Date to be compared
* @param inclusiveFrom Whether or not a Date equal to fromDate should be considered a match
* @param toDate The upper bound Date to be compared
* @param inclusiveTo Whether or not a Date equal to toDate should be considered a match
* @return Date A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Date dateBetween(Date fromDate, Boolean inclusiveFrom, Date toDate, Boolean inclusiveTo)
{
return (Date)matches(new fflib_MatcherDefinitions.DatetimeBetween(fromDate, inclusiveFrom, toDate, inclusiveTo));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches datetimeAfter (not inclusive)
* @param fromDate The Datetime to be compared
* @return Datetime A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Datetime datetimeAfter(Datetime fromDate)
{
return datetimeAfter(fromDate, false);
}
/**
* Registers a matcher which will check if the method is called with an arg that matches datetimeAfter
* @param fromDate The Datetime to be compared
* @param inclusive Whether or not a Datetime equal to fromDate should be considered a match
* @return Datetime A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Datetime datetimeAfter(Datetime fromDate, Boolean inclusive)
{
return (Datetime)matches(new fflib_MatcherDefinitions.DatetimeAfter(fromDate, inclusive));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches datetimeBefore (not inclusive)
* @param toDate The Datetime to be compared
* @return Datetime A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Datetime datetimeBefore(Datetime toDate)
{
return datetimeBefore(toDate, false);
}
/**
* Registers a matcher which will check if the method is called with an arg that matches datetimeBefore
* @param toDate The Datetime to be compared
* @param inclusive Whether or not a Datetime equal to toDate should be considered a match
* @return Datetime A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Datetime datetimeBefore(Datetime toDate, Boolean inclusive)
{
return (Datetime)matches(new fflib_MatcherDefinitions.DatetimeBefore(toDate, inclusive));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches datetimeBetween (not inclusive)
* @param fromDate The lower bound Datetime to be compared
* @param toDate The upper bound Datetime to be compared
* @return Datetime A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Datetime datetimeBetween(Datetime fromDate, Datetime toDate)
{
return datetimeBetween(fromDate, false, toDate, false);
}
/**
* Registers a matcher which will check if the method is called with an arg that matches datetimeBetween
* @param fromDate The lower bound Datetime to be compared
* @param inclusiveFrom Whether or not a Datetime equal to fromDate should be considered a match
* @param toDate The upper bound Datetime to be compared
* @param inclusiveTo Whether or not a Datetime equal to toDate should be considered a match
* @return Datetime A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Datetime datetimeBetween(Datetime fromDate, Boolean inclusiveFrom, Datetime toDate, Boolean inclusiveTo)
{
return (Datetime)matches(new fflib_MatcherDefinitions.DatetimeBetween(fromDate, inclusiveFrom, toDate, inclusiveTo));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches decimalBetween (not inclusive)
* @param lower The lower number to be compared
* @param upper The upper number to be compared
* @return Decimal A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Decimal decimalBetween(Decimal lower, Decimal upper)
{
return decimalBetween(lower, false, upper, false);
}
/**
* Registers a matcher which will check if the method is called with an arg that matches decimalBetween
* @param lower The lower number to be compared
* @param inclusiveLower Whether or not a number equal to the lower bound should be considered a match
* @param upper The upper number to be compared
* @param inclusiveUpper Whether or not a number equal to the upper bound should be considered a match
* @return Decimal A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Decimal decimalBetween(Decimal lower, Boolean inclusiveLower, Decimal upper, Boolean inclusiveUpper)
{
return (Decimal)matches(new fflib_MatcherDefinitions.DecimalBetween(lower, inclusiveLower, upper, inclusiveUpper));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches decimalLessThan (not inclusive)
* @param toMatch The number to be compared
* @return Decimal A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Decimal decimalLessThan(Decimal toMatch)
{
return decimalLessThan(toMatch, false);
}
/**
* Registers a matcher which will check if the method is called with an arg that matches decimalLessThan
* @param toMatch The number to be compared
* @param inclusive Whether or not a number equal to toMatch should be considered a match
* @return Decimal A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Decimal decimalLessThan(Decimal toMatch, Boolean inclusive)
{
return (Decimal)matches(new fflib_MatcherDefinitions.DecimalLessThan(toMatch, inclusive));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches decimalMoreThan (not inclusive)
* @param toMatch The number to be compared
* @return Decimal A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Decimal decimalMoreThan(Decimal toMatch)
{
return decimalMoreThan(toMatch, false);
}
/**
* Registers a matcher which will check if the method is called with an arg that matches decimalMoreThan
* @param toMatch The number to be compared
* @param inclusive Whether or not a number equal to toMatch should be considered a match
* @return Decimal A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Decimal decimalMoreThan(Decimal toMatch, Boolean inclusive)
{
return (Decimal)matches(new fflib_MatcherDefinitions.DecimalMoreThan(toMatch, inclusive));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches doubleBetween (not inclusive)
* @param lower The lower number to be compared
* @param upper The upper number to be compared
* @return Double A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Double doubleBetween(Double lower, Double upper)
{
return doubleBetween(lower, false, upper, false);
}
/**
* Registers a matcher which will check if the method is called with an arg that matches doubleBetween
* @param lower The lower number to be compared
* @param inclusiveLower Whether or not a number equal to the lower bound should be considered a match
* @param upper The upper number to be compared
* @param inclusiveUpper Whether or not a number equal to the upper bound should be considered a match
* @return Double A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Double doubleBetween(Double lower, Boolean inclusiveLower, Double upper, Boolean inclusiveUpper)
{
return (Double)matches(new fflib_MatcherDefinitions.DecimalBetween(lower, inclusiveLower, upper, inclusiveUpper));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches doubleLessThan (not inclusive)
* @param toMatch The number to be compared
* @return Double A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Double doubleLessThan(Double toMatch)
{
return doubleLessThan(toMatch, false);
}
/**
* Registers a matcher which will check if the method is called with an arg that matches doubleLessThan
* @param toMatch The number to be compared
* @param inclusive Whether or not a number equal to toMatch should be considered a match
* @return Double A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Double doubleLessThan(Double toMatch, Boolean inclusive)
{
return (Double)matches(new fflib_MatcherDefinitions.DecimalLessThan(toMatch, inclusive));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches doubleMoreThan (not inclusive)
* @param toMatch The number to be compared
* @return Double A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Double doubleMoreThan(Double toMatch)
{
return doubleMoreThan(toMatch, false);
}
/**
* Registers a matcher which will check if the method is called with an arg that matches doubleMoreThan
* @param toMatch The number to be compared
* @param inclusive Whether or not a number equal to toMatch should be considered a match
* @return Double A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Double doubleMoreThan(Double toMatch, Boolean inclusive)
{
return (Double)matches(new fflib_MatcherDefinitions.DecimalMoreThan(toMatch, inclusive));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches FieldSetEquivalentTo
* @param toMatch The fieldSet to be compared
* @return Schema.FieldSet A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Schema.FieldSet fieldSetEquivalentTo(Schema.FieldSet toMatch)
{
return (Schema.FieldSet)matches(new fflib_MatcherDefinitions.FieldSetEquivalentTo(toMatch));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches integerBetween (not inclusive)
* @param lower The lower number to be compared
* @param upper The upper number to be compared
* @return Integer A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Integer integerBetween(Integer lower, Integer upper)
{
return integerBetween(lower, false, upper, false);
}
/**
* Registers a matcher which will check if the method is called with an arg that matches integerBetween
* @param lower The lower number to be compared
* @param inclusiveLower Whether or not a number equal to the lower bound should be considered a match
* @param upper The upper number to be compared
* @param inclusiveUpper Whether or not a number equal to the upper bound should be considered a match
* @return Integer A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Integer integerBetween(Integer lower, Boolean inclusiveLower, Integer upper, Boolean inclusiveUpper)
{
return (Integer)matches(new fflib_MatcherDefinitions.DecimalBetween(lower, inclusiveLower, upper, inclusiveUpper));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches integerLessThan (not inclusive)
* @param toMatch The number to be compared
* @return Integer A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Integer integerLessThan(Integer toMatch)
{
return integerLessThan(toMatch, false);
}
/**
* Registers a matcher which will check if the method is called with an arg that matches integerLessThan
* @param toMatch The number to be compared
* @param inclusive Whether or not a number equal to toMatch should be considered a match
* @return Integer A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Integer integerLessThan(Integer toMatch, Boolean inclusive)
{
return (Integer)matches(new fflib_MatcherDefinitions.DecimalLessThan(toMatch, inclusive));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches integerMoreThan (not inclusive)
* @param toMatch The number to be compared
* @return Integer A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Integer integerMoreThan(Integer toMatch)
{
return integerMoreThan(toMatch, false);
}
/**
* Registers a matcher which will check if the method is called with an arg that matches integerMoreThan
* @param toMatch The number to be compared
* @param inclusive Whether or not a number equal to toMatch should be considered a match
* @return Integer A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Integer integerMoreThan(Integer toMatch, Boolean inclusive)
{
return (Integer)matches(new fflib_MatcherDefinitions.DecimalMoreThan(toMatch, inclusive));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches isNotNull
* @return Object A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked. (You may need to cast down to your specific object type)
*/
public static Object isNotNull()
{
return matches(new fflib_MatcherDefinitions.IsNotNull());
}
/**
* Registers a matcher which will check if the method is called with an arg that matches isNull
* @return Object A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked. (You may need to cast down to your specific object type)
*/
public static Object isNull()
{
return matches(new fflib_MatcherDefinitions.IsNull());
}
/**
* Registers a matcher which will check if the method is called with an arg that matches listContains
* @param toMatch The list to be compared
* @return Object A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked. (You may need to cast down to your specific object type)
*/
public static Object listContains(Object toMatch)
{
return matches(new fflib_MatcherDefinitions.ListContains(toMatch));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches listIsEmpty
* @return Object A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked. (You may need to cast down to your specific object type)
*/
public static Object listIsEmpty()
{
return matches(new fflib_MatcherDefinitions.ListIsEmpty());
}
/**
* Registers a matcher which will check if the method is called with an arg that matches longBetween (not inclusive)
* @param lower The lower number to be compared
* @param upper The upper number to be compared
* @return Long A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Long longBetween(Long lower, Long upper)
{
return longBetween(lower, false, upper, false);
}
/**
* Registers a matcher which will check if the method is called with an arg that matches longBetween
* @param lower The lower number to be compared
* @param inclusiveLower Whether or not a number equal to the lower bound should be considered a match
* @param upper The upper number to be compared
* @param inclusiveUpper Whether or not a number equal to the upper bound should be considered a match
* @return Long A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Long longBetween(Long lower, Boolean inclusiveLower, Long upper, Boolean inclusiveUpper)
{
return (Long)matches(new fflib_MatcherDefinitions.DecimalBetween(lower, inclusiveLower, upper, inclusiveUpper));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches longLessThan (not inclusive)
* @param toMatch The number to be compared
* @return Long A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Long longLessThan(Long toMatch)
{
return longLessThan(toMatch, false);
}
/**
* Registers a matcher which will check if the method is called with an arg that matches longLessThan
* @param toMatch The number to be compared
* @param inclusive Whether or not a number equal to toMatch should be considered a match
* @return Long A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Long longLessThan(Long toMatch, Boolean inclusive)
{
return (Long)matches(new fflib_MatcherDefinitions.DecimalLessThan(toMatch, inclusive));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches longMoreThan (not inclusive)
* @param toMatch The number to be compared
* @return Long A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Long longMoreThan(Long toMatch)
{
return longMoreThan(toMatch, false);
}
/**
* Registers a matcher which will check if the method is called with an arg that matches longMoreThan
* @param toMatch The number to be compared
* @param inclusive Whether or not a number equal to toMatch should be considered a match
* @return Long A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static Long longMoreThan(Long toMatch, Boolean inclusive)
{
return (Long)matches(new fflib_MatcherDefinitions.DecimalMoreThan(toMatch, inclusive));
}
/**
* Registers a matcher which will check if the method is called with an SObject of specified SObjectType
* @param objectType The SObjectType to be compared
* @return SObject a dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked
*/
public static SObject sObjectOfType(Schema.SObjectType objectType)
{
return (SObject)matches(new fflib_MatcherDefinitions.SObjectOfType(objectType));
}
/**
* Registers a matcher which will check if the method is called with an SObject
* @param toMatch A Map of SObjectFields to required values, to be compared to concrete SObject records
* @return SObject a dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked
*/
public static SObject sObjectWith(Map toMatch)
{
return (SObject)matches(new fflib_MatcherDefinitions.SObjectWith(toMatch));
}
/**
* Registers a matcher which will check if the method is called with a list of SObject
* @param toMatch A list of Map of SObjectFields to required values, to be compared to concrete SObject records
* @return SObject a dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked
*/
public static SObject[] sObjectsWith(list> toMatch)
{
return (SObject[])matches(new fflib_MatcherDefinitions.SObjectsWith(toMatch,true));
}
/**
* Registers a matcher which will check if the method is called with a list of SObject
* @param toMatch A list of Map of SObjectFields to required values, to be compared to concrete SObject records. Comparison can be order dependent
* @return SObject a dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked
*/
public static SObject[] sObjectsWith(list> toMatch, Boolean matchInOrder)
{
return (SObject[])matches(new fflib_MatcherDefinitions.SObjectsWith(toMatch,matchInOrder));
}
/**
* Registers a matcher which will check if the method is called with an SObject
* @param toMatch The Id to be compared
* @return SObject a dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked
*/
public static SObject sObjectWithId(Id toMatch)
{
return (SObject)matches(new fflib_MatcherDefinitions.SObjectWithId(toMatch));
}
/**
* Registers a matcher which will check if the method is called with an SObject
* @param toMatch The name to be compared
* @return SObject a dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked
*/
public static SObject sObjectWithName(String toMatch)
{
return (SObject)matches(new fflib_MatcherDefinitions.SObjectWithName(toMatch));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches stringContains
* @param toMatch The substring to be compared
* @return String A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static String stringContains(String toMatch)
{
return (String)matches(new fflib_MatcherDefinitions.StringContains(toMatch));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches stringEndsWith
* @param toMatch The substring to be compared
* @return String A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static String stringEndsWith(String toMatch)
{
return (String)matches(new fflib_MatcherDefinitions.StringEndsWith(toMatch));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches stringIsBlank
* @return String A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static String stringIsBlank()
{
return (String)matches(new fflib_MatcherDefinitions.StringIsBlank());
}
/**
* Registers a matcher which will check if the method is called with an arg that matches stringIsNotBlank
* @return String A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static String stringIsNotBlank()
{
return (String)matches(new fflib_MatcherDefinitions.StringIsNotBlank());
}
/**
* Registers a matcher which will check if the method is called with an arg that matches stringMatches
* @param regEx The regex String to be compared
* @return String A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static String stringMatches(String regEx)
{
return (String)matches(new fflib_MatcherDefinitions.StringMatches(regEx));
}
/**
* Registers a matcher which will check if the method is called with an arg that matches stringStartsWith
* @param toMatch The substring to be compared
* @return String A dummy object of the correct type, so that when called inline as part of a method call, the correct method is invoked.
*/
public static String stringStartsWith(String toMatch)
{
return (String)matches(new fflib_MatcherDefinitions.StringStartsWith(toMatch));
}
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_Match.cls-meta.xml
================================================
63.0
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_MatcherDefinitions.cls
================================================
/**
* Copyright (c) 2014-2017, FinancialForce.com, inc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the FinancialForce.com, inc nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* Class providing Apex Mocks standard matcher implementations.
* You shouldn't need to reference the classes directly outside of the ApexMocks framework, instead use the equivalent helper method in fflib_Match
* to construct the matcher, register the matcher and return an object of the correct type to be called in your unit test.
* E.g. Don't construct Eq(Object toMatch), instead call fflib_Match.eq(Object toMatch).
*/
@NamespaceAccessible
public with sharing class fflib_MatcherDefinitions
{
/**
* Connective - Enum representing the possible operators for the Combined matcher. Possible values: ALL, AT_LEAST_ONE, NONE
*/
public Enum Connective
{
ALL,
AT_LEAST_ONE,
NONE
}
/*
* COMBINED MATCHER
*/
/**
* Combined matcher: compares the supplied argument matches one, all or none of the internal matchers
*/
@NamespaceAccessible
public class Combined implements fflib_IMatcher
{
private Connective connectiveExpression;
private List internalMatchers;
/**
* Combined constructor
* @param connectiveExpression Controls the combination mode, i.e. if we need to match all, any or none of the inner matchers
* @param internalMatchers An ordered list of the internal matchers to be combined
* @return fflib_MatcherDefinitions.Combined A new Combined instance
*/
public Combined(Connective connectiveExpression, List internalMatchers)
{
this.connectiveExpression = validate(connectiveExpression);
this.internalMatchers = validate(internalMatchers);
}
public Boolean matches(Object arg)
{
for (fflib_IMatcher internalMatcher : internalMatchers)
{
if (internalMatcher.matches(arg))
{
if (connectiveExpression == Connective.AT_LEAST_ONE)
{
//At least one match => success!
return true;
}
else if (connectiveExpression == Connective.NONE)
{
//At least one match => failure!
return false;
}
}
else if (connectiveExpression == Connective.ALL)
{
//At least one mismatch => failure!
return false;
}
}
//We didn't return early.
//If matching any, must have been no matches => failure!
//If matching all, must have been all matches => success!
//If matching none, must have been all mismatches => success!
return connectiveExpression != Connective.AT_LEAST_ONE;
}
private Connective validate(Connective connectiveExpression)
{
if (connectiveExpression == null)
{
throw new fflib_ApexMocks.ApexMocksException('Invalid connective expression: ' + connectiveExpression);
}
return connectiveExpression;
}
private List validate(List innerMatchers)
{
if (innerMatchers == null || innerMatchers.isEmpty())
{
throw new fflib_ApexMocks.ApexMocksException('Invalid inner matchers: ' + innerMatchers);
}
return innerMatchers;
}
public override String toString()
{
List internalDescriptions = new List();
for (fflib_IMatcher internalMatcher : internalMatchers)
{
internalDescriptions.add('' + internalMatcher);
}
String internalDescription = String.join(internalDescriptions, ', ');
switch on connectiveExpression
{
when AT_LEAST_ONE
{
return '[any of: ' + internalDescription + ']';
}
when ALL
{
return '[all of: ' + internalDescription + ']';
}
when else
{
return '[none of: ' + internalDescription + ']';
}
}
}
}
/*
* OBJECT MATCHERS
*/
/**
* Eq matcher: checks if the supplied argument is equal (==) to a specified object
*/
@NamespaceAccessible
public class Eq implements fflib_IMatcher
{
private Object toMatch;
/**
* Eq constructor
* @param toMatch The object to be compared
* @return fflib_MatcherDefinitions.Eq A new Eq instance
*/
public Eq(Object toMatch)
{
this.toMatch = validateNotNull(toMatch);
}
public Boolean matches(Object arg)
{
return toMatch == arg;
}
public override String toString()
{
return '[equals ' + stringify(toMatch) + ']';
}
}
/**
* RefEq matcher: checks if the supplied argument is a reference to the same object (===) as a specified object
*/
@NamespaceAccessible
public class RefEq implements fflib_IMatcher
{
private Object toMatch;
/**
* RefEq constructor
* @param toMatch The object to be compared
* @return fflib_MatcherDefinitions.RefEq A new RefEq instance
*/
public RefEq(Object toMatch)
{
this.toMatch = validateNotNull(toMatch);
}
public Boolean matches(Object arg)
{
return toMatch === arg;
}
public override String toString()
{
return '[reference equals ' + fflib_MatcherDefinitions.stringify(toMatch) + ']';
}
}
/*
* ANY MATCHERS
*/
/**
* AnyBoolean matcher: checks if the supplied argument is an instance of a Boolean
*/
@NamespaceAccessible
public class AnyBoolean implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg != null && arg instanceof Boolean;
}
public override String toString()
{
return '[any Boolean]';
}
}
/**
* AnyDate matcher: checks if the supplied argument is an instance of a Date
*/
@NamespaceAccessible
public class AnyDate implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg != null && arg instanceof Date;
}
public override String toString()
{
return '[any Date]';
}
}
/**
* AnyDatetime matcher: checks if the supplied argument is an instance of a Datetime
@NamespaceAccessible
*/
public class AnyDatetime implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg != null && arg instanceof Datetime;
}
public override String toString()
{
return '[any DateTime]';
}
}
/**
@NamespaceAccessible
* AnyDecimal matcher: checks if the supplied argument is an instance of a Decimal
*/
public class AnyDecimal implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg != null && arg instanceof Decimal;
}
public override String toString()
{
return '[any Decimal]';
}
}
/**
* AnyDouble matcher: checks if the supplied argument is an instance of a Double
*/
@NamespaceAccessible
public class AnyDouble implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg != null && arg instanceof Double;
}
public override String toString()
{
return '[any Double]';
}
}
/**
* AnyFieldSet matcher: checks if the supplied argument is an instance of a FieldSet
*/
@NamespaceAccessible
public class AnyFieldSet implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg != null && arg instanceof Schema.FieldSet;
}
public override String toString()
{
return '[any FieldSet]';
}
}
/**
* AnyId matcher: checks if the supplied argument is an instance of an Id
@NamespaceAccessible
*/
public class AnyId implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg != null && arg instanceof Id;
}
public override String toString()
{
return '[any Id]';
}
}
/**
@NamespaceAccessible
* AnyInteger matcher: checks if the supplied argument is an instance of an Integer
*/
public class AnyInteger implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg != null && arg instanceof Integer;
}
public override String toString()
{
return '[any Integer]';
}
}
/**
* AnyList matcher: checks if the supplied argument is an instance of a List
*/
@NamespaceAccessible
public class AnyList implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg != null && arg instanceof List;
}
public override String toString()
{
return '[any list]';
}
}
/**
* AnyLong matcher: checks if the supplied argument is an instance of a Long
*/
@NamespaceAccessible
public class AnyLong implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg != null && arg instanceof Long;
}
public override String toString()
{
return '[any Long]';
}
}
/**
* AnyObject matcher: checks if the supplied argument is an instance of an Object
*/
public class AnyObject implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg != null;
}
public override String toString()
{
return '[any Object]';
}
}
/**
* AnyString matcher: checks if the supplied argument is an instance of a String
*/
@NamespaceAccessible
public class AnyString implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg != null && arg instanceof String;
}
public override String toString()
{
return '[any String]';
}
}
/**
* AnySObject matcher: checks if the supplied argument is an instance of an SObject
*/
@NamespaceAccessible
public class AnySObject implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg != null && arg instanceof SObject;
}
public override String toString()
{
return '[any SObject]';
}
}
/**
* AnySObjectField matcher: checks if the supplied argument is an instance of an SObjectField
*/
@NamespaceAccessible
public class AnySObjectField implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg != null && arg instanceof SObjectField;
}
public override String toString()
{
return '[any SObjectField]';
}
}
/**
* AnySObjectType matcher: checks if the supplied argument is an instance of an SObjectType
@NamespaceAccessible
*/
public class AnySObjectType implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg != null && arg instanceof SObjectType;
}
public override String toString()
{
return '[any SObjectType]';
}
}
/*
* DATETIME MATCHERS
*/
/**
* DatetimeAfter matcher: checks if the supplied argument is after a specified datetime
*/
@NamespaceAccessible
public class DatetimeAfter implements fflib_IMatcher
{
private Datetime fromDatetime;
private Boolean inclusive;
/**
* DatetimeAfter constructor
* @param fromDatetime The datetime to be compared
* @param inclusive Whether or not dates equal to the fromDatetime should be considered a match
* @return fflib_MatcherDefinitions.DatetimeAfter A new DatetimeAfter instance
*/
public DatetimeAfter(Datetime fromDatetime, Boolean inclusive)
{
this.fromDatetime = (Datetime)validateNotNull(fromDatetime);
this.inclusive = (Boolean)validateNotNull(inclusive);
}
public Boolean matches(Object arg)
{
if (arg instanceof Datetime)
{
Datetime datetimeToCompare = (Datetime)arg;
return inclusive ? fromDatetime <= datetimeToCompare : fromDatetime < datetimeToCompare;
}
return false;
}
public override String toString()
{
if (inclusive)
{
return '[on or after ' + JSON.serialize(fromDateTime) + ']';
}
else
{
return '[after ' + JSON.serialize(fromDateTime) + ']';
}
}
}
/**
* DatetimeBefore matcher: checks if the supplied argument is before a specified datetime
*/
@NamespaceAccessible
public class DatetimeBefore implements fflib_IMatcher
{
private Datetime toDatetime;
private Boolean inclusive;
/**
* DatetimeBefore constructor
* @param toDatetime The datetime to be compared
* @param inclusive Whether or not dates equal to the toDatetime should be considered a match
* @return fflib_MatcherDefinitions.DatetimeBefore A new DatetimeBefore instance
*/
public DatetimeBefore(Datetime toDatetime, Boolean inclusive)
{
this.toDatetime = (Datetime)validateNotNull(toDatetime);
this.inclusive = (Boolean)validateNotNull(inclusive);
}
public Boolean matches(Object arg)
{
if (arg instanceof Datetime)
{
Datetime datetimeToCompare = (Datetime)arg;
return inclusive ? datetimeToCompare <= toDatetime : datetimeToCompare < toDatetime;
}
return false;
}
public override String toString()
{
if (inclusive)
{
return '[on or before ' + JSON.serialize(toDateTime) + ']';
}
else
{
return '[before ' + JSON.serialize(toDateTime) + ']';
}
}
}
/**
* DatetimeBetween matcher: checks if the supplied argument is between two specified datetimes
*/
@NamespaceAccessible
public class DatetimeBetween implements fflib_IMatcher
{
private Datetime fromDatetime;
private Boolean inclusiveFrom;
private Datetime toDatetime;
private Boolean inclusiveTo;
/**
* DatetimeBetween constructor
* @param fromDatetime The lower bound datetime to be compared
* @param inclusiveFrom Whether or not dates equal to the fromDatetime should be considered a match
* @param toDatetime The upper bound dateetime to be compared
* @param inclusiveTo Whether or not dates equal to the toDatetime should be considered a match
* @return fflib_MatcherDefinitions.DatetimeBetween A new DatetimeBetween instance
*/
public DatetimeBetween(Datetime fromDatetime, Boolean inclusiveFrom, Datetime toDatetime, Boolean inclusiveTo)
{
this.fromDatetime = (Datetime)validateNotNull(fromDatetime);
this.inclusiveFrom = (Boolean)validateNotNull(inclusiveFrom);
this.toDatetime = (Datetime)validateNotNull(toDatetime);
this.inclusiveTo = (Boolean)validateNotNull(inclusiveTo);
}
public Boolean matches(Object arg)
{
if (arg instanceof Datetime)
{
Datetime datetimeToCompare = (Datetime)arg;
if ((inclusiveFrom ? datetimeToCompare >= fromDatetime : datetimeToCompare > fromDatetime)
&& (inclusiveTo ? datetimeToCompare <= toDatetime : datetimeToCompare < toDatetime))
{
return true;
}
}
return false;
}
public override String toString()
{
return String.format('[{0} {1} and {2} {3}]', new List{
inclusiveFrom ? 'on or after' : 'after',
JSON.serialize(fromDateTime),
inclusiveTo ? 'on or before' : 'before',
JSON.serialize(toDateTime)
});
}
}
/*
* DECIMAL (AND OTHER NUMBER) MATCHERS
*/
/**
* DecimalBetween matcher: checks if the supplied argument is between two specified decimals
*/
@NamespaceAccessible
public class DecimalBetween implements fflib_IMatcher
{
private Decimal lower;
private Boolean inclusiveLower;
private Decimal upper;
private Boolean inclusiveUpper;
/**
* DecimalBetween constructor
* @param lower The lower bound number to be compared
* @param inclusiveLower Whether or not numbers equal to lower should be considered a match
* @param upper The upper bound number to be compared
* @param inclusiveUpper Whether or not numbers equal to upper should be considered a match
* @return fflib_MatcherDefinitions.DecimalBetween A new DecimalBetween instance
*/
public DecimalBetween(Decimal lower, Boolean inclusiveLower, Decimal upper, Boolean inclusiveUpper)
{
this.lower = (Decimal)validateNotNull(lower);
this.inclusiveLower = (Boolean)validateNotNull(inclusiveLower);
this.upper = (Decimal)validateNotNull(upper);
this.inclusiveUpper = (Boolean)validateNotNull(inclusiveUpper);
}
public Boolean matches(Object arg)
{
if (arg != null && arg instanceof Decimal)
{
Decimal longArg = (Decimal)arg;
if ((inclusiveLower ? longArg >= lower : longArg > lower)
&& (inclusiveUpper ? longArg <= upper : longArg < upper))
{
return true;
}
}
return false;
}
public override String toString()
{
return String.format('{0} {1} and {2} {3}', new List{
inclusiveLower ? 'greater than or equal to' : 'greater than',
'' + lower,
inclusiveUpper ? 'less than or equal to' : 'less than',
'' + upper
});
}
}
/**
* DecimalLessThan matcher: checks if the supplied argument is less than a specified decimal
*/
@NamespaceAccessible
public class DecimalLessThan implements fflib_IMatcher
{
private Decimal toMatch;
private Boolean inclusive;
/**
* DecimalLessThan constructor
* @param toMatch The number to be compared against
* @param inclusive Whether or not numbers equal to toMatch should be considered a match
* @return fflib_MatcherDefinitions.DecimalLessThan A new DecimalLessThan instance
*/
public DecimalLessThan(Decimal toMatch, Boolean inclusive)
{
this.toMatch = (Decimal)validateNotNull(toMatch);
this.inclusive = (Boolean)validateNotNull(inclusive);
}
public Boolean matches(Object arg)
{
if (arg != null && arg instanceof Decimal)
{
Decimal longArg = (Decimal)arg;
return inclusive ? longArg <= toMatch : longArg < toMatch;
}
return false;
}
public override String toString()
{
if (inclusive)
{
return '[less than or equal to ' + toMatch + ']';
}
else
{
return '[less than ' + toMatch + ']';
}
}
}
/**
* DecimalMoreThan matcher: checks if the supplied argument is greater than a specified decimal
*/
@NamespaceAccessible
public class DecimalMoreThan implements fflib_IMatcher
{
private Decimal toMatch;
private Boolean inclusive;
/**
* DecimalMoreThan constructor
* @param toMatch The number to be compared against
* @param inclusive Whether or not numbers equal to toMatch should be considered a match
* @return fflib_MatcherDefinitions.DecimalMoreThan A new DecimalMoreThan instance
*/
public DecimalMoreThan(Decimal toMatch, Boolean inclusive)
{
this.toMatch = (Decimal)validateNotNull(toMatch);
this.inclusive = (Boolean)validateNotNull(inclusive);
}
public Boolean matches(Object arg)
{
if (arg != null && arg instanceof Decimal)
{
Decimal longArg = (Decimal)arg;
return inclusive ? longArg >= toMatch : longArg > toMatch;
}
return false;
}
public override String toString()
{
if (inclusive)
{
return '[greater than or equal to ' + toMatch + ']';
}
else
{
return '[greater than ' + toMatch + ']';
}
}
}
/**
* FIELDSET MATCHERS
*/
/**
* FieldSetEquivalentTo matcher: checks the supplied argument is a field set with the same field set members as a specified field set
* This matcher is needed because equivalent FieldSets do not pass == checks, and we can't override equals/hashcode on FieldSets.
*/
@NamespaceAccessible
public class FieldSetEquivalentTo implements fflib_IMatcher
{
private final Set toMatch;
/*
* Dirty test-only constructor, allowing us to test this class even if there are no field sets defined in the current org.
*/
@TestVisible
public FieldSetEquivalentTo()
{
this.toMatch = null;
}
public FieldSetEquivalentTo(Schema.FieldSet toMatch)
{
this.toMatch = new Set(((Schema.FieldSet)validateNotNull(toMatch)).getFields());
}
public Boolean matches(Object arg)
{
return (toMatch != null && arg != null && arg instanceof Schema.FieldSet) ? toMatch == new Set(((FieldSet)arg).getFields()) : false;
}
public override String toString()
{
return '[FieldSet with fields ' + fflib_MatcherDefinitions.stringify(toMatch) + ']';
}
}
/*
* IS MATCHERS
*/
/**
* IsNotNull matcher: checks the supplied argument is not null
@NamespaceAccessible
*/
public class IsNotNull implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg != null;
}
public override String toString()
{
return '[is not null]';
}
}
/**
* IsNull matcher: checks the supplied argument is null
*/
@NamespaceAccessible
public class IsNull implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg == null;
}
public override String toString()
{
return '[is null]';
}
}
/*
* LIST MATCHERS
*/
/**
* ListContains matcher: checks if the supplied argument is equal (==) to any of the elements in a specified list
*/
@NamespaceAccessible
public class ListContains implements fflib_IMatcher
{
private Object toMatch;
/**
* ListContains constructor
* @param toMatch The list of objects to be compared
* @return fflib_MatcherDefinitions.ListContains A new ListContains instance
*/
public ListContains(Object toMatch)
{
this.toMatch = toMatch;
}
public Boolean matches(Object arg)
{
if (arg != null && arg instanceof List)
{
for (Object o : (List)arg)
{
if (o == toMatch)
{
return true;
}
}
}
return false;
}
public override String toString()
{
return '[list containing ' + fflib_MatcherDefinitions.stringify(toMatch) + ']';
}
}
/**
* ListIsEmpty matcher: checks if the supplied argument is an empty list
@NamespaceAccessible
*/
public class ListIsEmpty implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg != null
&& arg instanceof List
&& ((List)arg).isEmpty();
}
public override String toString()
{
return '[empty list]';
}
}
/*
* SOBJECT MATCHERS
*/
/**
* SObjectOfType matcher: checks if the supplied argument has the specified SObjectType
@NamespaceAccessible
*/
public class SObjectOfType implements fflib_IMatcher
{
private Schema.SObjectType objectType;
/**
* SObjectOfType constructor
* @param objectType The SObjectType to be compared
* @return fflib_MatcherDefinitions.SObjectOfType A new SObjectOfType instance
*/
public SObjectOfType(Schema.SObjectType objectType)
{
this.objectType = (Schema.SObjectType)validateNotNull(objectType);
}
public Boolean matches(Object arg)
{
if (arg != null && arg instanceof SObject)
{
SObject soArg = (SObject)arg;
return soArg.getSObjectType() == objectType;
}
return false;
}
public override String toString()
{
return '[SObject of type ' + objectType + ']';
}
}
/**
* SObjectWith matcher: compares the supplied argument against a Map, representing fields and their expected values.
* Note. this method silently catches exceptions getting values for the supplied fields from the arguments supplied in method calls.
*
* If your matcher is mysteriously failing for your SObject record, it may be getting silent 'SObject row was retrieved via SOQL without querying
* the requested field' exceptions, because you haven't queried all of the fields used in this matcher.
*/
@NamespaceAccessible
public class SObjectWith implements fflib_IMatcher
{
private Map toMatch;
/**
* SObjectWith constructor
* @param toMatch A map of fields to their values to be compared. We compare each of these fields against the supplied sobject's field values.
* @return fflib_MatcherDefinitions.SObjectWith A new SObjectWith instance
*/
public SObjectWith(Map toMatch)
{
this.toMatch = validate(toMatch);
}
public Boolean matches(Object arg)
{
if (arg != null && arg instanceof SObject)
{
SObject soArg = (SObject)arg;
if (!sobjectMatches(soArg,this.toMatch))
{
return false;
}
return true;
}
return false;
}
private Map validate(Map arg)
{
if (arg == null || arg.isEmpty())
{
throw new fflib_ApexMocks.ApexMocksException('Arg cannot be null/empty: ' + arg);
}
return arg;
}
public override String toString()
{
return '[SObject with fields ' + fflib_MatcherDefinitions.stringify(toMatch) + ']';
}
}
/**
* SObjectsWith matcher: compares the supplied list argument against a list>, representing fields and their expected values.
* Each list element represents one Sobject in a list supplied to a mocked method that accepts list.
* Each list element that is a map is compared against the equivalent argument list element position
*
* Example:
* You use uow.registerNew(someListofAccounts). You mock uow in the testmethod.
* toMatch is new list {
* new map {Account.Name => 'foo'},
* new map {Account.Name => 'bar'}
* }
* By default, matchers compare against argument elements in order, viz:
* The matcher will compare the first Account in the list passed to uow.registerNew to the first map of field values (i.e. Account[0].Name must be 'foo')
* The matcher then compares the second Account in the list passed to uow.registerNew to the second map of field values (i.e. Account[1].Name must be 'bar')
*
* Optional second argument matchInOrderr if false means that each argument element is compared against all matcher elements
* if everuy argument is matched exactly once and no matcher matches more than once, then the match is true
*
* If the arity of the list passed in the mocked method doesn't agree with the arity of the map of expected field values, false is returned
*
* Note. this method silently catches exceptions getting values for the supplied fields from the arguments supplied in method calls.
*
* If your matcher is mysteriously failing for your SObject record, it may be getting silent 'SObject row was retrieved via SOQL without querying
* the requested field' exceptions, because you haven't queried all of the fields used in this matcher.
*/
@NamespaceAccessible
public class SObjectsWith implements fflib_IMatcher
{
private list> toMatch;
private Boolean matchInOrder {
get
{
return matchInOrder == null ? false : matchInOrder;
}
set;
}
/**
* SObjectsWith constructor
* @param toMatch A list of maps of fields to their values to be compared. We compare each of these fields against the supplied list of sobject's field values.
* @return fflib_MatcherDefinitions.SObjectWith A new SObjectWith instance
*/
public SObjectsWith(list> toMatch, Boolean matchInOrder)
{
this.toMatch = validate(toMatch);
this.matchInOrder = matchInOrder;
}
public SObjectsWith(list> toMatch)
{
this.toMatch = validate(toMatch);
this.matchInOrder = true;
}
public Boolean matches(Object arg)
{
if (arg != null && arg instanceof list)
{
SObject[] sobjsArg = (SObject[])arg;
list> toMatches = new list>();
// Counters for matchInOrder = false; not relevant for matchInOrder = true
list argMatchedCounts = new list(); // # times matched by a matcher. anything other than 1 is match error
list matcherMatchedCounts = new list(); // for each map
// # args that match it. Anything other than 1 is match error
for (map mtchElm : toMatch)
{
toMatches.add(mtchElm);
matcherMatchedCounts.add(0);
}
if (sobjsArg.size() != toMatches.size()) // arity of arguments to mocked method doesn't agree with arity of expected matches
{
return false;
}
if (matchInOrder)
{
for (Integer i = 0; i < sobjsArg.size(); i++)
{ // match in order (toMatch[i] must match arg[i])
if (!sobjectMatches(sobjsArg[i],toMatches[i]))
{
return false;
}
}
return true;
}
else
{
// match in any order (but every arg must be matched only once)
for (Integer i = 0; i < sobjsArg.size(); i++)
{
argMatchedCounts.add(0);
// For each arg passed to mocked method, see if any match in the list of match field maps.
// Loop within loop so not hugely efficient but there are no IDs to rely on.
// Avoid unit test methods that build huge lists of expected results
for (Integer m = 0; m < toMatches.size(); m++)
{
if (sobjectMatches(sobjsArg[i],toMatches[m]))
{
argMatchedCounts[i] ++;
matcherMatchedCounts[m] ++;
}
}
}
// Check to see that every arg was matched only once
// Check to see that every matcher matched only once
// Anything else is a match fail
for (Integer i=0; i < argMatchedCounts.size(); i++)
{
if (argMatchedCounts[i] != 1 || matcherMatchedCounts[i] != 1)
{
return false;
}
}
return true;
}
}
return false;
}
private list> validate(list> arg)
{
if (arg == null || arg.isEmpty() )
{
throw new fflib_ApexMocks.ApexMocksException('Arg cannot be null/empty/other than list of map: ' + arg);
}
return arg;
}
public override String toString()
{
if (matchInOrder)
{
return '[ordered SObjects with ' + fflib_MatcherDefinitions.stringify(toMatch) + ']';
}
else
{
return '[unordered SObjects with ' + fflib_MatcherDefinitions.stringify(toMatch) + ']';
}
}
}
/**
* helper for the sObjectWith, sObjectsWith matchers
* Compares to see if the field values in toMatch exist in the sobj
**/
private static Boolean sObjectMatches(Sobject sobj, map toMatch)
{
for (Schema.SObjectField f : toMatch.keySet())
{
Object valueToMatch = toMatch.get(f);
try
{
if (sobj.get(f) != valueToMatch)
{
return false;
}
}
catch (Exception e)
{
//If we fail to get the value for a field it's either:
// - 'SObject row was retrieved via SOQL without querying the requested field' as a mismatch
// - System.SObjectException - Account.Id does not belong to SObject type Opportunity
//Don't care too much, just treat this as a mismatch.
return false;
}
}
return true; // map of expected fieldvals found in sobj arg
}
/**
* SObjectWithId matcher: checks if the supplied argument has the specified Id
*/
@NamespaceAccessible
public class SObjectWithId implements fflib_IMatcher
{
private Id toMatch;
/**
* SObjectWithId constructor
* @param toMatch The Id to be compared
* @return fflib_MatcherDefinitions.SObjectWithId A new SObjectWithId instance
*/
public SObjectWithId(Id toMatch)
{
this.toMatch = (Id)validateNotNull(toMatch);
}
public Boolean matches(Object arg)
{
if (arg != null && arg instanceof SObject)
{
SObject soArg = (SObject)arg;
return soArg.Id == toMatch;
}
return false;
}
public override String toString()
{
return '[SObject with Id "' + toMatch + '"]';
}
}
/**
* SObjectWithName matcher: checks if the supplied argument has the specified Name
@NamespaceAccessible
*/
public class SObjectWithName implements fflib_IMatcher
{
private String toMatch;
/**
* SObjectWithName constructor
* @param toMatch The name to be compared
* @return fflib_MatcherDefinitions.SObjectWithName A new SObjectWithName instance
*/
public SObjectWithName(String toMatch)
{
this.toMatch = (String)validateNotNull(toMatch);
}
public Boolean matches(Object arg)
{
if (arg != null && arg instanceof SObject)
{
SObject soArg = (SObject)arg;
Schema.DescribeSObjectResult describe = soArg.getSObjectType().getDescribe();
for (Schema.SObjectField f : describe.fields.getMap().values())
{
if (f.getDescribe().isNameField())
{
return soArg.get(f) == toMatch;
}
}
}
return false;
}
public override String toString()
{
return '[SObject with Name "' + toMatch + '"]';
}
}
/*
* STRING MATCHERS
*/
/**
* StringContains matcher: checks if the supplied argument contains the specified substring
*/
@NamespaceAccessible
public class StringContains implements fflib_IMatcher
{
private String toMatch;
/**
* StringContains constructor
* @param toMatch The substring to be compared
* @return fflib_MatcherDefinitions.StringContains A new StringContains instance
*/
public StringContains(String toMatch)
{
this.toMatch = (String)validateNotNull(toMatch);
}
public Boolean matches(Object arg)
{
return arg != null && arg instanceof String ? ((String)arg).contains(toMatch) : false;
}
public override String toString()
{
return '[contains "' + toMatch + '"]';
}
}
/**
* StringEndsWith matcher: checks if the supplied argument ends with the specified substring
*/
@NamespaceAccessible
public class StringEndsWith implements fflib_IMatcher
{
private String toMatch;
/**
* StringEndsWith constructor
* @param toMatch The substring to be compared
* @return fflib_MatcherDefinitions.StringEndsWith A new StringEndsWith instance
*/
public StringEndsWith(String toMatch)
{
this.toMatch = (String)validateNotNull(toMatch);
}
public Boolean matches(Object arg)
{
return arg != null && arg instanceof String ? ((String)arg).endsWith(toMatch) : false;
}
public override String toString()
{
return '[ends with "' + toMatch + '"]';
}
}
/**
* StringIsBlank matcher: checks if the supplied argument is a blank String
@NamespaceAccessible
*/
public class StringIsBlank implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg == null || (arg instanceof String ? String.isBlank((String)arg) : false);
}
public override String toString()
{
return '[blank String]';
}
}
/**
@NamespaceAccessible
* StringIsNotBlank matcher: checks if the supplied argument is a non-blank string
*/
public class StringIsNotBlank implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return (arg != NULL && arg instanceof String) ? String.isNotBlank((String)arg) : false;
}
public override String toString()
{
return '[non-blank String]';
}
}
/**
* StringMatches matcher: checks if the supplied argument matches the specified regex expression
*/
@NamespaceAccessible
public class StringMatches implements fflib_IMatcher
{
private Pattern pat;
private final String regEx;
/**
* StringMatches constructor
* @param toMatch The substring to be compared
* @return fflib_MatcherDefinitions.StringMatches A new StringMatches instance
*/
public StringMatches(String regEx)
{
this.regEx = regEx;
this.pat = Pattern.compile((String)validateNotNull(regEx));
}
public Boolean matches(Object arg)
{
return arg != null && arg instanceof String ? pat.matcher((String)arg).matches() : false;
}
public override String toString()
{
return '[matches regex "' + regEx + '"]';
}
}
/**
* StringStartsWith matcher: checks if the supplied argument starts with the specified substring
*/
@NamespaceAccessible
public class StringStartsWith implements fflib_IMatcher
{
private String toMatch;
/**
* StringStartsWith constructor
* @param toMatch The substring to be compared
* @return fflib_MatcherDefinitions.StringStartsWith A new StringStartsWith instance
*/
public StringStartsWith(String toMatch)
{
this.toMatch = (String)validateNotNull(toMatch);
}
public Boolean matches(Object arg)
{
return arg != null && arg instanceof String ? ((String)arg).startsWith(toMatch) : false;
}
public override String toString()
{
return '[starts with "' + toMatch + '"]';
}
}
/*
* Helpers
*/
private static Object validateNotNull(Object arg)
{
if (arg == null)
{
throw new fflib_ApexMocks.ApexMocksException('Arg cannot be null: ' + arg);
}
return arg;
}
public static String stringify(Object value)
{
try
{
return JSON.serialize(value, false);
}
catch (Exception error)
{
return '' + value;
}
}
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_MatcherDefinitions.cls-meta.xml
================================================
63.0
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_MatchersReturnValue.cls
================================================
/**
* Copyright (c) 2014-2016, FinancialForce.com, inc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the FinancialForce.com, inc nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@NamespaceAccessible
public with sharing class fflib_MatchersReturnValue
{
public List matchers;
public fflib_MethodReturnValue returnValue;
public fflib_MatchersReturnValue(List matchers, fflib_MethodReturnValue returnValue)
{
this.matchers = matchers;
this.returnValue = returnValue;
}
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_MatchersReturnValue.cls-meta.xml
================================================
63.0
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_MethodArgValues.cls
================================================
/**
* Copyright (c) 2014-2016, FinancialForce.com, inc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the FinancialForce.com, inc nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@NamespaceAccessible
public with sharing class fflib_MethodArgValues
{
public List argValues;
/**
* Wrapper object which encapsulates the argument values
* supplied during a given method call.
* @param argValues The
* @return fflib_MethodArgValues The method argument wrapper object
*/
@NamespaceAccessible
public fflib_MethodArgValues(List argValues)
{
this.argValues = argValues;
}
/**
* Standard equals override.
* @param other The object whose equality we are verifying
* @return Boolean True if meaningfully equivalent, false otherwise.
*/
public Boolean equals(Object other)
{
if (this === other)
{
return true;
}
fflib_MethodArgValues that = other instanceof fflib_MethodArgValues ? (fflib_MethodArgValues)other : null;
return that != null && this.argValues == that.argValues;
}
/**
* Standard hashCode override.
* @return Integer The generated hashCode
*/
public Integer hashCode()
{
Integer prime = 31;
Integer result = 1;
result = prime * result + ((argValues == null) ? 0 : argValues.hashCode());
return result;
}
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_MethodArgValues.cls-meta.xml
================================================
63.0
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_MethodCountRecorder.cls
================================================
/*
Copyright (c) 2014-2017 FinancialForce.com, inc. All rights reserved.
*/
/**
* @group Core
*/
@NamespaceAccessible
public with sharing class fflib_MethodCountRecorder
{
/*
* Map of method arguments by type name.
*
* Key: qualifiedMethod
* Object: list of method arguments.
*
* Object: map of count by method call argument.
*/
private static Map> methodArgumentsByTypeName =
new Map>();
private static List orderedMethodCalls =
new List();
/**
* Getter for the list of the methods ordered calls.
* @return The list of methods called in order.
*/
public static List getOrderedMethodCalls()
{
return orderedMethodCalls;
}
/**
* Getter for the map of the method's calls with the related arguments.
* @return The map of methods called with the arguments.
*/
public static Map> getMethodArgumentsByTypeName()
{
return methodArgumentsByTypeName;
}
/**
* Record a method was called on a mock object.
* @param invocation The object holding all the data of the invocation, like the method and arguments and the mock instance.
*/
public void recordMethod(fflib_InvocationOnMock invocation)
{
List methodArgs =
methodArgumentsByTypeName.get(invocation.getMethod());
if (methodArgs == null)
{
methodArgs = new List();
methodArgumentsByTypeName.put(invocation.getMethod(), methodArgs);
}
methodArgs.add(invocation.getMethodArgValues());
orderedMethodCalls.add(invocation);
}
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_MethodCountRecorder.cls-meta.xml
================================================
63.0
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_MethodReturnValue.cls
================================================
/*
* Copyright (c) 2014-2017, FinancialForce.com, inc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the FinancialForce.com, inc nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @group Core
* Class defining a method return value.
*/
@isTest
@NamespaceAccessible
public with sharing class fflib_MethodReturnValue
{
private StandardAnswer basicAnswer = new StandardAnswer();
/**
* Instance of the implementation of the Answer interface that implements the answer,
* if an answer isn't explicitly set the standard answer will be used, which just returns the stubbed return value.
*/
public fflib_Answer Answer { get; set; }
/**
* Setup a stubbed return value.
* @param value The value to return from the stubbed method call.
* @return The fflib_MethodReturnValue instance to allow you to chain the methods.
*/
@NamespaceAccessible
public fflib_MethodReturnValue thenReturn(Object value)
{
thenAnswer(this.basicAnswer.setValue(value));
return this;
}
/**
* Setup a stubbed exception.
* @param e The exception to throw from the stubbed method call.
* @return The fflib_MethodReturnValue instance to allow you to chain the methods.
*/
@NamespaceAccessible
public fflib_MethodReturnValue thenThrow(Exception e)
{
thenAnswer(this.basicAnswer.setValue(e));
return this;
}
/**
* Setup a stubbed answer.
* @param answer The answer to run from the stubbed method call.
*/
@NamespaceAccessible
public void thenAnswer(fflib_Answer answer)
{
this.Answer = answer;
}
/**
* Setup a list of stubbed return values.
* @param values The values to return from the stubbed method call in consecutive calls.
* @return The fflib_MethodReturnValue instance to allow you to chain the methods.
*/
@NamespaceAccessible
public fflib_MethodReturnValue thenReturnMulti(List values)
{
thenAnswer(this.basicAnswer.setValues(values));
return this;
}
/**
* Setup a list stubbed exceptions.
* @param es The exceptions to throw from the stubbed method call in consecutive calls.
* @return The fflib_MethodReturnValue instance to allow you to chain the methods.
*/
@NamespaceAccessible
public fflib_MethodReturnValue thenThrowMulti(List es)
{
thenAnswer(this.basicAnswer.setValues(es));
return this;
}
/**
* @group Core
* Inner class to handle all the stubs that do not use the thenAnswer method directly.
* For internal use only.
*/
@NamespaceAccessible
public class StandardAnswer implements fflib_Answer
{
private Integer whichStubReturnIndex = 0;
/*
* It stores the return values for the method stubbed.
* The values would be stored and then returned as part of the standard answer invocation.
*/
private List ReturnValues = new List();
/**
* Setter of a single return value.
* @param value The value to be set as return value for the StandardAnswer object.
* @return The StandardAnswer instance.
*/
public StandardAnswer setValue(Object value)
{
ReturnValues.add(value);
return this;
}
/**
* Setter of the list of return values.
* @param value The value to be set as return value for the StandardAnswer object.
* @return the StandardAnswer instance.
*/
public StandardAnswer setValues(List values)
{
if(values == null || values.size() == 0)
{
throw new fflib_ApexMocks.ApexMocksException(
'The stubbing is not correct, no return values have been set.');
}
ReturnValues.addAll(values);
return this;
}
/**
* Standard basic implementation for the fflib_Answer answer method, to be used as default answering.
* @param invocation The invocation to answer for.
* @return The ReturnValue for the method stubbed.
*/
public Object answer(fflib_InvocationOnMock invocation)
{
if(ReturnValues == null || ReturnValues.size() == 0)
{
throw new fflib_ApexMocks.ApexMocksException(
'The stubbing is not correct, no return values have been set.');
}
Integer returnValuesSize = ReturnValues.size()-1;
if(whichStubReturnIndex < returnValuesSize)
{
return ReturnValues[whichStubReturnIndex++];
}
else
{
return ReturnValues[returnValuesSize];
}
}
}
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_MethodReturnValue.cls-meta.xml
================================================
63.0
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_MethodReturnValueRecorder.cls
================================================
/*
* Copyright (c) 2014, FinancialForce.com, inc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the FinancialForce.com, inc nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @group Core
*/
@NamespaceAccessible
public with sharing class fflib_MethodReturnValueRecorder
{
public Boolean Stubbing { get; set; }
public List DoThrowWhenExceptions { get; set; }
/**
* Map of matchers by method.
*
* Key: qualifiedMethod
* Object: map of method return values by method.
*/
private Map> matcherReturnValuesByMethod;
public fflib_MethodReturnValue MethodReturnValue { get; private set; }
public fflib_MethodReturnValueRecorder()
{
matcherReturnValuesByMethod = new Map>();
MethodReturnValue = null;
}
/**
* Prepare a stubbed method return value.
* @param invocation The object holding all the data of the invocation, like the method and arguments and the mock instance.
* @return The MethodReturnValue instance.
*/
public fflib_MethodReturnValue prepareMethodReturnValue(fflib_InvocationOnMock invocation)
{
MethodReturnValue = new fflib_MethodReturnValue();
List matcherReturnValues = matcherReturnValuesByMethod.get(invocation.getMethod());
if (matcherReturnValues == null)
{
matcherReturnValues = new List();
matcherReturnValuesByMethod.put(invocation.getMethod(), matcherReturnValues);
}
List argValues = invocation.getMethodArgValues().argValues;
//Register explicit arg values as 'equals' matchers, to preserve old behaviour
if (!fflib_Match.Matching)
{
for (Object arg : argValues)
{
if (arg == null)
fflib_Match.isNull();
else
fflib_Match.eq(arg);
}
}
List matchers = fflib_Match.getAndClearMatchers(argValues.size());
matcherReturnValues.add(new fflib_MatchersReturnValue(matchers, MethodReturnValue));
return MethodReturnValue;
}
/**
* Get the method return value for the given method call.
* @param invocation The object holding all the data of the invocation, like the method and arguments and the mock instance.
* @return The MethodReturnValue instance.
*/
public fflib_MethodReturnValue getMethodReturnValue(fflib_InvocationOnMock invocation)
{
List matchersForMethods = matcherReturnValuesByMethod.get(invocation.getMethod());
if (matchersForMethods != null)
{
for (Integer i = matchersForMethods.size() - 1; i >= 0; i--)
{
fflib_MatchersReturnValue matchersReturnValue = (fflib_MatchersReturnValue)matchersForMethods.get(i);
if (fflib_Match.matchesAllArgs(invocation.getMethodArgValues(), matchersReturnValue.matchers))
{
return matchersReturnValue.ReturnValue;
}
}
}
return null;
}
/**
* Prepare a stubbed exceptions for a void method.
* @param exps The list of exception to throw.
*/
public void prepareDoThrowWhenExceptions(List exps)
{
DoThrowWhenExceptions = exps;
}
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_MethodReturnValueRecorder.cls-meta.xml
================================================
63.0
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_MethodVerifier.cls
================================================
/*
Copyright (c) 2017 FinancialForce.com, inc. All rights reserved.
*/
/**
* This class implements the actual verification.
* @group Core
*/
@NamespaceAccessible
public abstract class fflib_MethodVerifier
{
/**
* Verify a method was called on a mock object.
* @param mockInvocation The object holding all the data of the invocation, like the method and arguments and the mock instance.
* @param verificationMode The verification mode that holds the setting about how the verification should be performed.
*/
public void verifyMethodCall(fflib_InvocationOnMock mockInvocation, fflib_VerificationMode verificationMode)
{
validateMode(verificationMode);
verify(mockinvocation.getMethod(), mockinvocation.getMethodArgValues(), verificationMode);
}
/*
* Method that actually performs the verify
* @param qm The method to be verified.
* @param methodArg The arguments of the method that needs to be verified.
* @param verificationMode The verification mode that holds the setting about how the verification should be performed.
*/
protected abstract void verify(
fflib_QualifiedMethod qm,
fflib_MethodArgValues methodArg,
fflib_VerificationMode verificationMode);
/*
* Method that validates the verification mode used in the verify.
* Not all the methods from the fflib_VerificationMode are implemented for the different classes that extends the fflib_MethodVerifier.
* The error is thrown at run time, so this method is called in the method that actually performs the verify.
* @param verificationMode The verification mode that has to have been verified.
* @throws Exception with message for the fflib_VerificationMode not implemented.
*/
protected abstract void validateMode(fflib_VerificationMode verificationMode);
/*
* Method that performs the argument capturing.
* Captures argument values during verification.
* @param matchers The list of matcher with which a method is verified.
*/
protected void capture(List matchers)
{
for(fflib_IMatcher matcher : matchers)
{
if( matcher instanceof fflib_ArgumentCaptor.AnyObject )
{
((fflib_ArgumentCaptor.AnyObject)matcher).storeArgument();
}
}
}
protected void throwException(
fflib_QualifiedMethod qm,
String inOrder,
Integer expectedCount,
String qualifier,
Integer methodCount,
String customAssertMessage,
fflib_MethodArgValues expectedArguments,
List expectedMatchers,
List actualArguments)
{
String template = 'EXPECTED COUNT: {0}{1}{2}' // qualified expected count (e.g. "3 or fewer times in order")
+ '\nACTUAL COUNT: {3}' // actual count
+ '\nMETHOD: {4}' // method signature
+ '{5}'; // custom assert message
String expectedDescription = '';
String actualDescription = '';
if (qm.hasArguments())
{
template += '\n---' // separator
+ '\nACTUAL ARGS: {6}' // actual args
+ '\n---' // separator
+ '\nEXPECTED ARGS: {7}'; // matcher descriptions
if (expectedMatchers == null)
{
expectedDescription = describe(expectedArguments);
}
else
{
expectedDescription = describe(expectedMatchers);
}
actualDescription = describe(actualArguments);
}
String message = String.format(template, new List{
'' + expectedCount,
String.isBlank(qualifier) ? '' : ('' + qualifier),
inOrder,
'' + methodCount,
'' + qm,
String.isBlank(customAssertMessage) ? '' : ('\n' + customAssertMessage),
actualDescription,
expectedDescription
});
throw new fflib_ApexMocks.ApexMocksException(message);
}
private static String describe(List matchers)
{
List descriptions = new List();
for (fflib_IMatcher matcher : matchers)
{
descriptions.add('' + matcher);
}
return String.join(descriptions, ', ');
}
private static String describe(List valuesFromAllInvocations)
{
List descriptions = new List();
if (valuesFromAllInvocations != null)
{
for (fflib_MethodArgValues valuesFromOneInvocation : valuesFromAllInvocations)
{
descriptions.add(describe(valuesFromOneInvocation));
}
}
return '(' + String.join(descriptions, '), (') + ')';
}
private static String describe(fflib_MethodArgValues values)
{
List descriptions = new List();
for (Object value : values.argValues)
{
try
{
// Attempt to JSON serialize - that way it doesn't truncate SObject fields etc.
// Bear in mind that something are not JSON serializable, e.g. things with circular references.
descriptions.add(JSON.serialize(value));
}
catch (Exception error)
{
descriptions.add('' + value);
}
}
return String.join(descriptions, ', ');
}
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_MethodVerifier.cls-meta.xml
================================================
63.0
Active
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_QualifiedMethod.cls
================================================
/*
* Copyright (c) 2016-2017 FinancialForce.com, inc. All rights reserved.
*/
@NamespaceAccessible
public with sharing class fflib_QualifiedMethod
{
public final Object mockInstance;
public final String typeName;
public final String methodName;
public final List methodArgTypes;
@NamespaceAccessible
public fflib_QualifiedMethod(String typeName, String methodName, List methodArgTypes)
{
this(typeName, methodName, methodArgTypes, null);
}
@NamespaceAccessible
public fflib_QualifiedMethod(String typeName, String methodName, List methodArgTypes, Object mockInstance)
{
this.mockInstance = mockInstance;
this.typeName = typeName;
this.methodName = methodName;
this.methodArgTypes = methodArgTypes;
}
/**
* Standard equals override.
* @param other The object whose equality we are verifying
* @return Boolean True if meaningfully equivalent, false otherwise.
*/
public Boolean equals(Object other)
{
if (this === other)
{
return true;
}
fflib_QualifiedMethod that = other instanceof fflib_QualifiedMethod ? (fflib_QualifiedMethod)other : null;
return that != null
&& (this.mockInstance === that.mockInstance || !fflib_ApexMocksConfig.HasIndependentMocks)
&& this.typeName == that.typeName
&& this.methodName == that.methodName
&& this.methodArgTypes == that.methodArgTypes;
}
/**
* Standard hashCode override.
* @return Integer The generated hashCode
*/
public Integer hashCode()
{
Integer prime = 31;
Integer result = 1;
if (fflib_ApexMocksConfig.HasIndependentMocks)
{
result = prime * result + ((mockInstance == null) ? 0 : mockInstance.hashCode());
}
result = prime * result + ((methodArgTypes == null) ? 0 : methodArgTypes.hashCode());
result = prime * result + ((methodName == null) ? 0 : methodName.hashCode());
result = prime * result + ((typeName == null) ? 0 : typeName.hashCode());
return result;
}
/**
* Standard toString override.
* @return String The human friendly description of the method.
*/
public override String toString()
{
return typeName + '.' + methodName + methodArgTypes;
}
/**
* Predicate describing whether the qualified method accepts arguments or not.
* @return True if the method accepts arguments.
*/
public Boolean hasArguments()
{
return this.methodArgTypes != null && !this.methodArgTypes.isEmpty();
}
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_QualifiedMethod.cls-meta.xml
================================================
63.0
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_QualifiedMethodAndArgValues.cls
================================================
/*
Copyright (c) 2016-2017 FinancialForce.com, inc. All rights reserved.
*/
/**
* @group Core
*/
@NamespaceAccessible
public with sharing class fflib_QualifiedMethodAndArgValues
{
private final fflib_QualifiedMethod qm;
private final fflib_MethodArgValues args;
private final Object mockInstance;
@NamespaceAccessible
public fflib_QualifiedMethodAndArgValues(fflib_QualifiedMethod qm, fflib_MethodArgValues args, Object mockInstance)
{
this.qm = qm;
this.args = args;
this.mockInstance = mockInstance;
}
@NamespaceAccessible
public fflib_QualifiedMethod getQualifiedMethod()
{
return qm;
}
@NamespaceAccessible
public fflib_MethodArgValues getMethodArgValues()
{
return args;
}
@NamespaceAccessible
public Object getMockInstance()
{
return mockInstance;
}
public override String toString()
{
return qm + ' with args: [' + String.join(args.argValues, '],[') + ']';
}
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_QualifiedMethodAndArgValues.cls-meta.xml
================================================
63.0
Active
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_System.cls
================================================
/*
* Copyright (c) 2017 FinancialForce.com, inc. All rights reserved.
*/
/**
* @group Core
* Contains counterparts for helper methods in the native System class.
*/
@NamespaceAccessible
public class fflib_System
{
/**
* Verifies that the supplied argument is meaningfully equivalent to the expected argument, as defined by its matcher.
* See fflib_SystemTest for examples of usage.
* @param ignoredRetval Dummy value, returned on registering an fflib_IMatcher.
* @param value The object instance upon which we are checking equality.
*/
@NamespaceAccessible
public static void assertEquals(Object ignoredRetval, Object value)
{
assertEquals(ignoredRetval, value, null);
}
/**
* Verifies that the supplied argument is meaningfully equivalent to the expected argument, as defined by its matcher.
* See fflib_SystemTest for examples of usage.
* @param ignoredRetval Dummy value, returned on registering an fflib_IMatcher.
* @param value The object instance upon which we are checking equality.
* @param customAssertMessage Provides context or additional information for the assertion.
*/
@NamespaceAccessible
public static void assertEquals(Object ignoredRetval, Object value, String customAssertMessage)
{
fflib_IMatcher matcher = null;
try
{
List matchers = fflib_Match.getAndClearMatchers(1);
matcher = matchers[0];
}
catch (fflib_ApexMocks.ApexMocksException e)
{
throw new fflib_ApexMocks.ApexMocksException('fflib_System.assertEquals expects you to register exactly 1 fflib_IMatcher (typically through the helpers in fflib_Match).');
}
if (!matcher.matches(value))
{
throw new fflib_ApexMocks.ApexMocksException(String.format('Expected : {0}, Actual: {1}{2}', new String[]{
String.valueOf(matcher),
String.valueOf(value),
String.isBlank(customAssertMessage) ? '' : (' -- ' + customAssertMessage)
}));
}
}
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_System.cls-meta.xml
================================================
63.0
Active
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_VerificationMode.cls
================================================
/*
Copyright (c) 2017 FinancialForce.com, inc. All rights reserved.
*/
/**
* This class implements the verification modes with Mockito syntax style.
* It can be used in the classic verify and in the ordered verify.
* @group Core
*/
@NamespaceAccessible
public with sharing class fflib_VerificationMode
{
public Integer VerifyMin {get; set;}
public Integer VerifyMax {get; set;}
public String CustomAssertMessage { get; set; }
public enum ModeName {times, atLeast, atMost, between, atLeastOnce, calls}
public ModeName Method;
@NamespaceAccessible
public fflib_VerificationMode()
{
VerifyMin = 1;
VerifyMax = null;
CustomAssertMessage = null;
Method = null;
}
/**
* Sets how many times the method is expected to be called.
* For InOrder verification we copy Mockito behavior which is as follows;
*
* Consume the specified number of matching invocations, ignoring non-matching invocations in between
* Fail an assert if the very next invocation matches, but additional matches can still exist so long as at least one non-matching invocation exists before them
*
* For example if you had a(); a(); b(); a();
* then inOrder.verify(myMock, 2)).a(); or inOrder.verify(myMock, 3)).a(); would pass but not inOrder.verify(myMock, 1)).a();
* @param times The number of times you expect the method to have been called.
* @return The fflib_VerificationMode object instance with the proper settings.
*/
@NamespaceAccessible
public fflib_VerificationMode times(Integer times)
{
this.Method = ModeName.times;
this.VerifyMin = this.VerifyMax = times;
return this;
}
/**
* Sets a custom assert message for the verify.
* @param customAssertMessage The custom message for the assert in case the assert is false. The custom message is queued to the default message.
* @return The fflib_VerificationMode object instance with the proper settings.
*/
@NamespaceAccessible
public fflib_VerificationMode description(String customAssertMessage)
{
this.CustomAssertMessage = customAssertMessage;
return this;
}
/**
* Sets the minimum number of times the method is expected to be called.
* With the InOrder verification it performs a greedy verification, which means it would consume all the instances of the method verified.
* @param atLeastTimes The minimum number of times you expect the method to have been called.
* @return The fflib_VerificationMode object instance with the proper settings.
*/
@NamespaceAccessible
public fflib_VerificationMode atLeast(Integer atLeastTimes)
{
this.Method = ModeName.atLeast;
this.VerifyMin = atLeastTimes;
return this;
}
/**
* Sets the maximum number of times the method is expected to be called. Not available in the InOrder verification.
* @param atMostTimes The maximum number of times the method is expected to be called.
* @return The fflib_VerificationMode object instance with the proper settings.
*/
@NamespaceAccessible
public fflib_VerificationMode atMost(Integer atMostTimes)
{
this.Method = ModeName.atMost;
this.VerifyMax = atMostTimes;
return this;
}
/**
* Sets that the method is called at least once.
* With the InOrder verification it performs a greedy verification, which means it would consume all the instances of the method verified.
* @return The fflib_VerificationMode object instance with the proper settings.
*/
@NamespaceAccessible
public fflib_VerificationMode atLeastOnce()
{
this.Method = ModeName.atLeastOnce;
this.VerifyMin = 1;
return this;
}
/**
* Sets the range of how many times the method is expected to be called. Not available in the InOrder verification.
* @param atLeastTimes The minimum number of times you expect the method to have been called.
* @param atMostTimes The maximum number of times the method is expected to be called.
* @return The fflib_VerificationMode object instance with the proper settings.
*/
@NamespaceAccessible
public fflib_VerificationMode between(Integer atLeastTimes, Integer atMostTimes)
{
this.Method = ModeName.between;
this.VerifyMin = atLeastTimes;
this.VerifyMax = atMostTimes;
return this;
}
/**
* Sets that the method is not expected to be called.
* @return The fflib_VerificationMode object instance with the proper settings.
*/
@NamespaceAccessible
public fflib_VerificationMode never()
{
this.VerifyMin = fflib_ApexMocks.NEVER;
this.VerifyMax = fflib_ApexMocks.NEVER;
return this;
}
/**
* Sets how many times the method is expected to be called for an InOrder verifier. Available Only with the InOrder verification.
* A verification mode using calls will not fail if the method is called more times than expected.
* @param callingTimes The number of times you expect the method to have been called in the InOrder verifying (no greedy verify).
* @return The fflib_VerificationMode object instance with the proper settings.
*/
@NamespaceAccessible
public fflib_VerificationMode calls(Integer callingTimes)
{
this.Method = ModeName.calls;
this.VerifyMin = callingTimes;
this.VerifyMax = null;
return this;
}
}
================================================
FILE: sfdx-source/apex-mocks/main/classes/fflib_VerificationMode.cls-meta.xml
================================================
63.0
Active
================================================
FILE: sfdx-source/apex-mocks/test/classes/fflib_AnswerTest.cls
================================================
/*
Copyright (c) 2017 FinancialForce.com, inc. All rights reserved.
*/
/**
* @nodoc
*/
@isTest
private class fflib_AnswerTest
{
private static fflib_InvocationOnMock actualInvocation = null;
@isTest
static void thatAnswersWithException()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(mockList.get2(0, 'Hi hi Hello Hi hi')).thenAnswer(new fflib_AnswerTest.ExceptionForAnswer());
mocks.stopStubbing();
// When
try
{
mockList.get2(0, 'Hi hi Hello Hi hi');
System.Assert.fail('an exception is expected to be thrown on the answer execution');
}
catch(fflib_ApexMocks.ApexMocksException ansExpt)
{
String expectedMessage = 'an error occurs on the execution of the answer';
// Then
System.Assert.areEqual(expectedMessage, ansExpt.getMessage(), 'the message from the answer is not as expected');
}
}
@isTest
static void thatStoresMethodIntoInvocationOnMock()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(mockList.get2(0, 'Hi hi Hello Hi hi')).thenAnswer(new fflib_AnswerTest.BasicAnswer());
mocks.stopStubbing();
// When
mockList.get2(0, 'Hi hi Hello Hi hi');
// Then
Object methodCalled = actualInvocation.getMethod();
System.Assert.isInstanceOfType(methodCalled, fflib_QualifiedMethod.class, 'the object returned is not a method as expected');
String expectedMethodSignature = fflib_MyList.getStubClassName() + '.get2(Integer, String)';
System.Assert.areEqual(expectedMethodSignature, ((fflib_QualifiedMethod)methodCalled).toString(), ' the method is no the one expected');
}
@isTest
static void thatAnswerOnlyForTheMethodStubbedWithAnswer()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(mockList.get(3)).thenReturn('ted');
mocks.when(mockList.get2(0, 'Hi hi Hello Hi hi')).thenAnswer(new fflib_AnswerTest.BasicAnswer());
mocks.stopStubbing();
// When
mockList.add('one');
String noAnswered = mockList.get(3);
mockList.get2(0, 'Hi hi Hello Hi hi');
// Then
Object methodCalled = actualInvocation.getMethod();
System.Assert.isInstanceOfType(methodCalled, fflib_QualifiedMethod.class, 'the object returned is not a method as expected');
String expectedMethodSignature = fflib_MyList.getStubClassName() + '.get2(Integer, String)';
System.Assert.areEqual(expectedMethodSignature, ((fflib_QualifiedMethod)methodCalled).toString(), ' the method is no the one expected');
System.Assert.areEqual('ted', noAnswered, 'the get method should have returned the stubbed string');
}
@isTest
static void thatMultipleAnswersAreHandled()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(mockList.get(3)).thenAnswer(new fflib_AnswerTest.FirstAnswer());
mocks.when(mockList.get2(0, 'Hi hi Hello Hi hi')).thenAnswer(new fflib_AnswerTest.SecondAnswer());
mocks.stopStubbing();
// When
mockList.add('one');
String answer1 = mockList.get(3);
String answer2 = mockList.get2(0, 'Hi hi Hello Hi hi');
System.Assert.areEqual('this is the first answer', answer1, 'the answer wasnt the one expected');
System.Assert.areEqual('and this is the second one', answer2, 'the answer wasnt the one expected');
}
@isTest
static void thatStoresMockInstanceIntoInvocationOnMock()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(mockList.get2(0, 'Hi hi Hello Hi hi')).thenAnswer(new fflib_AnswerTest.BasicAnswer());
mocks.stopStubbing();
// When
String mockCalled = mockList.get2(0, 'Hi hi Hello Hi hi');
// Then
System.Assert.isInstanceOfType(actualInvocation.getMock(), fflib_MyList.IList.class, 'the object returned is not a mock instance as expected');
System.Assert.areEqual(mockList, actualInvocation.getMock(), 'the mock returned should be the mockList used in the stubbing');
}
@isTest
static void thatMethodsParametersAreAccessible()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(mockList.get2(0, 'Hi hi Hello Hi hi')).thenAnswer(new fflib_AnswerTest.ProcessArgumentAnswer());
mocks.stopStubbing();
// When
String actualValue = mockList.get2(0, 'Hi hi Hello Hi hi');
// Then
System.Assert.areEqual('Bye hi Hello Bye hi', actualValue, 'the answer is not correct');
}
@isTest
static void thatAnswerOnlyForTheStubbedParameter()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(mockList.get2(0, 'Hi hi Hello Hi hi')).thenAnswer(new fflib_AnswerTest.ProcessArgumentAnswer());
mocks.stopStubbing();
// When
String actualValue1 = mockList.get2(0, 'some string for my method');
String actualValue2 = mockList.get2(0, 'Hi hi Hello Hi hi');
String actualValue3 = mockList.get2(0, 'another string for the same method');
// Then
System.Assert.areEqual('Bye hi Hello Bye hi', actualValue2, 'the answer is not correct');
System.Assert.areEqual(null, actualValue1, 'the answer is not correct');
System.Assert.areEqual(null, actualValue3, 'the answer is not correct');
}
@isTest
static void thatMethodsParametersAreAccessibleWhenCalledWithMatchers()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(mockList.get2(fflib_Match.anyInteger(), fflib_Match.anyString())).thenAnswer(new fflib_AnswerTest.ProcessArgumentAnswer());
mocks.stopStubbing();
// When
String actualValue = mockList.get2(0, 'Hi hi Hello Hi hi');
// Then
System.Assert.areEqual('Bye hi Hello Bye hi', actualValue, 'the answer is not correct');
}
@isTest
static void thatExceptionIsThrownWhenAccessOutOfIndexArgument()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(mockList.get2(0, 'Hi hi Hello Hi hi')).thenAnswer(new fflib_AnswerTest.ExceptionForArgumentsOutOfBound());
mocks.stopStubbing();
// When
String actualValue = mockList.get2(0, 'Hi hi Hello Hi hi');
}
@isTest
static void thatExceptionIsThrownWhenAccessNegativeIndexArgument()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(mockList.get2(0, 'Hi hi Hello Hi hi')).thenAnswer(new fflib_AnswerTest.ExceptionForNegativeArgumentIndex());
mocks.stopStubbing();
// When
String actualValue = mockList.get2(0, 'Hi hi Hello Hi hi');
}
@isTest
static void thatArgumentListEmptyForMethodWithNoArgument()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(mockList.isEmpty()).thenAnswer(new fflib_AnswerTest.ArgumentListEmptyForMethodWithNoArgument());
mocks.stopStubbing();
// When
Boolean actualValue = mockList.isEmpty();
}
@isTest
static void thatAnswerToVoidMethod()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
((fflib_MyList) mocks.doAnswer(new fflib_AnswerTest.BasicAnswer(), mockList)).addMore('Hi hi Hello Hi hi');
mocks.stopStubbing();
// When
mockList.addMore('Hi hi Hello Hi hi');
// Then
Object methodCalled = actualInvocation.getMethod();
System.Assert.isInstanceOfType(methodCalled, fflib_QualifiedMethod.class, 'the object returned is not a method as expected');
String expectedMethodSignature = fflib_MyList.getStubClassName() + '.addMore(String)';
System.Assert.areEqual(expectedMethodSignature, ((fflib_QualifiedMethod)methodCalled).toString(), 'Unexpected method name: ' + methodCalled);
}
@isTest
static void thatAnswerToVoidAndNotVoidMethods()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
((fflib_MyList) mocks.doAnswer(new fflib_AnswerTest.FirstAnswer(), mockList)).get(3);
((fflib_MyList) mocks.doAnswer(new fflib_AnswerTest.BasicAnswer(), mockList)).addMore('Hi hi Hello Hi hi');
((fflib_MyList) mocks.doAnswer(new fflib_AnswerTest.SecondAnswer(), mockList)).get2(4, 'Hi hi Hello Hi hi');
mocks.stopStubbing();
// When
String answer1 = mockList.get(3);
String answer2 = mockList.get2(4, 'Hi hi Hello Hi hi');
mockList.addMore('Hi hi Hello Hi hi');
// Then
Object methodCalled = actualInvocation.getMethod();
System.Assert.isInstanceOfType(methodCalled, fflib_QualifiedMethod.class, 'the object returned is not a method as expected');
String expectedMethodSignature = fflib_MyList.getStubClassName() + '.addMore(String)';
System.Assert.areEqual(expectedMethodSignature, ((fflib_QualifiedMethod)methodCalled).toString(),
'the last method called should be the addMore, so should be the last to set the actualInvocation variable.');
System.Assert.areEqual('this is the first answer', answer1, 'the answer was not the one expected');
System.Assert.areEqual('and this is the second one', answer2, 'the answer was not the one expected');
}
@isTest
static void thatAnswerToDifferentVoidMethods()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
fflib_AnswerTest.FirstAnswer answer1 = new fflib_AnswerTest.FirstAnswer();
fflib_AnswerTest.SecondAnswer answer2 = new fflib_AnswerTest.SecondAnswer();
System.Assert.areEqual(null, answer1.getMessage(), 'the answer message should be null at this stage');
System.Assert.areEqual(null, answer2.getMessage(), 'the answer message should be null at this stage');
mocks.startStubbing();
((fflib_MyList) mocks.doAnswer(answer1, mockList)).addMore('Hi hi Hello Hi hi');
((fflib_MyList) mocks.doAnswer(answer2, mockList)).add('Hello');
mocks.stopStubbing();
// When
mockList.addMore('Hi hi Hello Hi hi');
mockList.add('Hello');
// Then
System.Assert.areEqual('this is the first answer', answer1.getMessage(), 'the answer was not the one expected');
System.Assert.areEqual('and this is the second one', answer2.getMessage(), 'the answer was not the one expected');
}
//Answers
public class BasicAnswer implements fflib_Answer
{
public Object answer(fflib_InvocationOnMock invocation)
{
actualInvocation = invocation;
return null;
}
}
public class ExceptionForAnswer implements fflib_Answer
{
public Object answer(fflib_InvocationOnMock invocation)
{
actualInvocation = invocation;
throw new fflib_ApexMocks.ApexMocksException('an error occurs on the execution of the answer');
}
}
public class ExceptionForArgumentsOutOfBound implements fflib_Answer
{
public Object answer(fflib_InvocationOnMock invocation)
{
actualInvocation = invocation;
try
{
Object noExistingObj = invocation.getArgument(2);
System.Assert.fail('an exception was expected because the argument in the method are only 2');
}
catch(fflib_ApexMocks.ApexMocksException exp)
{
String expectedMessage = 'Invalid index, must be greater or equal to zero and less of 2.';
String actualMessage = exp.getMessage();
System.Assert.areEqual(expectedMessage, actualMessage, 'the message return by the exception is not as expected');
}
return null;
}
}
public class ExceptionForNegativeArgumentIndex implements fflib_Answer
{
public Object answer(fflib_InvocationOnMock invocation)
{
actualInvocation = invocation;
try
{
Object noExistingObj = invocation.getArgument(-1);
System.Assert.fail('an exception was expected because the argument index cannot be negative');
}
catch(fflib_ApexMocks.ApexMocksException exp)
{
String expectedMessage = 'Invalid index, must be greater or equal to zero and less of 2.';
String actualMessage = exp.getMessage();
System.Assert.areEqual(expectedMessage, actualMessage, 'the message return by the exception is not as expected');
}
return null;
}
}
public class ArgumentListEmptyForMethodWithNoArgument implements fflib_Answer
{
public Object answer(fflib_InvocationOnMock invocation)
{
actualInvocation = invocation;
List emptyList = invocation.getArguments();
System.Assert.areEqual(0, emptyList.size(), 'the argument list from a method without arguments should be empty');
return null;
}
}
public class FirstAnswer implements fflib_Answer
{
private String answerMessage;
public String getMessage()
{
return this.answerMessage;
}
public Object answer(fflib_InvocationOnMock invocation)
{
actualInvocation = invocation;
this.answerMessage = 'this is the first answer';
return answerMessage;
}
}
public class SecondAnswer implements fflib_Answer
{
private String answerMessage;
public String getMessage()
{
return this.answerMessage;
}
public Object answer(fflib_InvocationOnMock invocation)
{
actualInvocation = invocation;
this.answerMessage = 'and this is the second one';
return answerMessage;
}
}
public class ProcessArgumentAnswer implements fflib_Answer
{
public Object answer(fflib_InvocationOnMock invocation)
{
actualInvocation = invocation;
String argument = (String) invocation.getArgument(1);
System.Assert.areNotEqual(null, argument, ' the argument should have some value');
argument = argument.replace('Hi', 'Bye');
return argument;
}
}
}
================================================
FILE: sfdx-source/apex-mocks/test/classes/fflib_AnswerTest.cls-meta.xml
================================================
63.0
Active
================================================
FILE: sfdx-source/apex-mocks/test/classes/fflib_AnyOrderTest.cls
================================================
/*
Copyright (c) 2017 FinancialForce.com, inc. All rights reserved.
*/
/**
* @nodoc
*/
@isTest
private class fflib_AnyOrderTest
{
/*
* replicating the apex mocks tests with the new syntax
*/
@isTest
private static void whenVerifyMultipleCallsWithMatchersShouldReturnCorrectMethodCallCounts()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.times(2))).add(fflib_Match.anyString());
((fflib_MyList.IList) mocks.verify(mockList)).add('fred');
((fflib_MyList.IList) mocks.verify(mockList)).add(fflib_Match.stringContains('fred'));
}
@isTest
private static void whenVerifyWithCombinedMatchersShouldReturnCorrectMethodCallCounts()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.never())).add(
(String)fflib_Match.allOf(fflib_Match.eq('bob'), fflib_Match.stringContains('re'))
);
((fflib_MyList.IList) mocks.verify(mockList)).add(
(String)fflib_Match.allOf(fflib_Match.eq('fred'), fflib_Match.stringContains('re'))
);
((fflib_MyList.IList) mocks.verify(mockList, mocks.times(2))).add(
(String)fflib_Match.anyOf(fflib_Match.eq('bob'), fflib_Match.eq('fred'))
);
((fflib_MyList.IList) mocks.verify(mockList)).add(
(String)fflib_Match.anyOf(fflib_Match.eq('bob'), fflib_Match.eq('jack'))
);
((fflib_MyList.IList) mocks.verify(mockList, mocks.times(2))).add(
(String)fflib_Match.noneOf(fflib_Match.eq('jack'), fflib_Match.eq('tim'))
);
((fflib_MyList.IList) mocks.verify(mockList, mocks.times(2))).add(
(String)fflib_Match.noneOf(
fflib_Match.anyOf(fflib_Match.eq('jack'), fflib_Match.eq('jill')),
fflib_Match.allOf(fflib_Match.eq('tim'), fflib_Match.stringContains('i'))
)
);
((fflib_MyList.IList) mocks.verify(mockList, mocks.times(2))).add(
(String)fflib_Match.isNot(fflib_Match.eq('jack'))
);
}
@isTest
private static void whenVerifyCustomMatchersCanBeUsed()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.get(1);
mockList.get(2);
mockList.get(3);
mockList.get(4);
mockList.get(5);
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.times(3))).get((Integer)fflib_Match.matches(new isOdd()));
((fflib_MyList.IList) mocks.verify(mockList, mocks.times(2))).get((Integer)fflib_Match.matches(new isEven()));
}
@isTest
private static void verifyMultipleMethodCallsWithSameSingleArgument()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('bob');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.times(2))).add('bob');
}
@isTest
private static void verifyMethodNotCalled()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.get(0);
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.never())).add('bob');
((fflib_MyList.IList) mocks.verify(mockList)).get(0);
}
@isTest
private static void verifySingleMethodCallWithMultipleArguments()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.set(0, 'bob');
// Then
((fflib_MyList.IList) mocks.verify(mockList)).set(0, 'bob');
((fflib_MyList.IList) mocks.verify(mockList, mocks.never())).set(0, 'fred');
}
@isTest
private static void verifyMethodCallWhenNoCallsBeenMadeForType()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.never())).add('bob');
}
@isTest
private static void whenVerifyMethodNeverCalledMatchersAreReset()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.never())).get(fflib_Match.anyInteger());
((fflib_MyList.IList) mocks.verify(mockList)).add(fflib_Match.anyString());
}
/*
* times
*/
@isTest
private static void verifyTimesMethodHasBeenCalled()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('bob');
mockList.add('bob');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.times(3))).add('bob');
}
@isTest
private static void verifyTimesMethodHasBeenCalledWithMatchers()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob1');
mockList.add('bob2');
mockList.add('bob3');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.times(3))).add(fflib_Match.anyString());
}
@isTest
private static void thatVerifyTimesMethodFailsWhenCalledLessTimes()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('bob');
mockList.add('bob');
// Then
try
{
((fflib_MyList.IList) mocks.verify(mockList, mocks.times(4))).add('bob');
System.Assert.fail('an exception was expected');
}
catch(Exception exc)
{
assertFailMessage(exc.getMessage(), 4, 3);
}
}
@isTest
private static void thatVerifyTimesMethodFailsWhenCalledMoreTimes()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('bob');
mockList.add('bob');
// Then
try
{
((fflib_MyList.IList) mocks.verify(mockList, mocks.times(2))).add('bob');
System.Assert.fail('an exception was expected');
}
catch(Exception exc)
{
assertFailMessage(exc.getMessage(), 2, 3);
}
}
@isTest
private static void thatVerifyTimesMethodFailsWhenCalledLessTimesWithMatchers()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('bob');
mockList.add('bob');
// Then
try
{
((fflib_MyList.IList) mocks.verify(mockList, mocks.times(4))).add(fflib_Match.anyString());
System.Assert.fail('an exception was expected');
}
catch(Exception exc)
{
assertFailMessage(exc.getMessage(), 4, 3);
}
}
@isTest
private static void thatVerifyTimesMethodFailsWhenCalledMoreTimesWithMatchers()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('bob');
mockList.add('bob');
// Then
try
{
((fflib_MyList.IList) mocks.verify(mockList, mocks.times(2))).add(fflib_Match.anyString());
System.Assert.fail('an exception was expected');
}
catch(Exception exc)
{
assertFailMessage(exc.getMessage(), 2, 3);
}
}
/*
* description
*/
@isTest
private static void thatCustomMessageIsAdded()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('bob');
mockList.add('bob');
String customAssertMessage = 'Custom message to explain the reason of the verification';
// Then
try
{
((fflib_MyList.IList) mocks.verify(mockList, mocks.times(2).description(customAssertMessage))).add(fflib_Match.anyString());
System.Assert.fail('an exception was expected');
}
catch(Exception exc)
{
System.Assert.areEqual('EXPECTED COUNT: 2'
+ '\nACTUAL COUNT: 3'
+ '\nMETHOD: fflib_MyList__sfdc_ApexStub.add(String)'
+ '\nCustom message to explain the reason of the verification'
+ '\n---'
+ '\nACTUAL ARGS: ("bob"), ("bob"), ("bob")'
+ '\n---'
+ '\nEXPECTED ARGS: [any String]',
exc.getMessage(),
'Unexpected verify fail message');
}
}
/*
* atLeast
*/
@isTest
private static void thatVerifiesAtLeastNumberOfTimes()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
mockList.add('bob');
mockList.add('bob');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.atLeast(2))).add('bob');
}
@isTest
private static void thatVerifiesAtLeastNumberOfTimesWhenIsCalledMoreTimes()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
mockList.add('bob');
mockList.add('fred');
mockList.add('bob');
mockList.add('fred');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.atLeast(2))).add('bob');
}
@isTest
private static void thatThrownExceptionIfCalledLessThanAtLeastNumberOfTimes()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
mockList.add('bob');
// Then
try
{
((fflib_MyList.IList) mocks.verify(mockList, mocks.atLeast(3))).add('bob');
System.Assert.fail('an exception was expected because we are asserting that the method is called 3 times when instead is called only twice');
}
catch(fflib_ApexMocks.ApexMocksException ex)
{
System.Assert.areEqual('EXPECTED COUNT: 3 or more times'
+ '\nACTUAL COUNT: 2'
+ '\nMETHOD: fflib_MyList__sfdc_ApexStub.add(String)'
+ '\n---'
+ '\nACTUAL ARGS: ("bob"), ("fred"), ("bob")'
+ '\n---'
+ '\nEXPECTED ARGS: "bob"',
ex.getMessage(),
'Unexpected verify fail message');
}
}
@isTest
private static void thatVerifiesAtLeastNumberOfTimesWithMatchers()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.atLeast(2))).add(fflib_Match.anyString());
}
@isTest
private static void thatVerifiesAtLeastNumberOfTimesWhenIsCalledMoreTimesWithMatchers()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
mockList.add('fred');
mockList.add('fred');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.atLeast(2))).add(fflib_Match.anyString());
}
@isTest
private static void thatThrownExceptionIfCalledLessThanAtLeastNumberOfTimesWithMatchers()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
// Then
try
{
((fflib_MyList.IList) mocks.verify(mockList, mocks.atLeast(3))).add(fflib_Match.anyString());
System.Assert.fail('an exception was expected because we are asserting that the method is called 3 times when instead is called only twice');
}
catch(fflib_ApexMocks.ApexMocksException ex)
{
System.Assert.areEqual('EXPECTED COUNT: 3 or more times'
+ '\nACTUAL COUNT: 2'
+ '\nMETHOD: fflib_MyList__sfdc_ApexStub.add(String)'
+ '\n---'
+ '\nACTUAL ARGS: ("bob"), ("fred")'
+ '\n---'
+ '\nEXPECTED ARGS: [any String]',
ex.getMessage(),
'Unexpected verify fail message');
}
}
/*
* atMost
*/
@isTest
private static void thatVerifiesAtMostNumberOfTimes()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
mockList.add('bob');
mockList.add('bob');
mockList.add('fred');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.atMost(5))).add('bob');
}
@isTest
private static void thatVerifiesAtMostSameNumberOfTimes()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
mockList.add('bob');
mockList.add('bob');
mockList.add('fred');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.atMost(3))).add('bob');
}
@isTest
private static void thatThrownExceptionIfCalledMoreThanAtMostNumberOfTimes()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
mockList.add('fred');
mockList.add('bob');
mockList.add('bob');
mockList.add('bob');
mockList.add('fred');
// Then
try
{
((fflib_MyList.IList) mocks.verify(mockList, mocks.atMost(3))).add('bob');
System.Assert.fail('an exception was expected because we are asserting that the method is called 3 times when instead is called four times');
}
catch(fflib_ApexMocks.ApexMocksException ex)
{
System.Assert.areEqual('EXPECTED COUNT: 3 or fewer times'
+ '\nACTUAL COUNT: 4'
+ '\nMETHOD: fflib_MyList__sfdc_ApexStub.add(String)'
+ '\n---'
+ '\nACTUAL ARGS: ("bob"), ("fred"), ("fred"), ("bob"), ("bob"), ("bob"), ("fred")'
+ '\n---'
+ '\nEXPECTED ARGS: "bob"',
ex.getMessage(),
'Unexpected verify fail message');
}
}
@isTest
private static void thatVerifiesAtMostNumberOfTimesWithMatchers()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
mockList.add('fred');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.atMost(5))).add(fflib_Match.anyString());
}
@isTest
private static void thatVerifiesAtMostSameNumberOfTimesWithMatchers()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
mockList.add('fred');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.atMost(3))).add(fflib_Match.anyString());
}
@isTest
private static void thatThrownExceptionIfCalledMoreThanAtMostNumberOfTimesWithMatchers()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
mockList.add('fred');
mockList.add('fred');
// Then
try
{
((fflib_MyList.IList) mocks.verify(mockList, mocks.atMost(3))).add(fflib_Match.anyString());
System.Assert.fail('an exception was expected because we are asserting that the method is called 3 times when instead is called four times');
}
catch(fflib_ApexMocks.ApexMocksException ex)
{
System.Assert.areEqual('EXPECTED COUNT: 3 or fewer times'
+ '\nACTUAL COUNT: 4'
+ '\nMETHOD: fflib_MyList__sfdc_ApexStub.add(String)'
+ '\n---'
+ '\nACTUAL ARGS: ("bob"), ("fred"), ("fred"), ("fred")'
+ '\n---'
+ '\nEXPECTED ARGS: [any String]'
, ex.getMessage(),
'Unexpected verify fail message');
}
}
/*
* atLeastOnce
*/
@isTest
private static void thatVerifiesAtLeastOnceNumberOfTimes()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
mockList.add('fred');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.atLeastOnce())).add('bob');
}
@isTest
private static void thatVerifiesAtLeastOnceNumberOfTimesWhenIsCalledMoreTimes()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
mockList.add('bob');
mockList.add('fred');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.atLeastOnce())).add('bob');
}
@isTest
private static void thatThrownExceptionIfCalledLessThanAtLeastOnceNumberOfTimes()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('rob');
mockList.add('fred');
// Then
try
{
((fflib_MyList.IList) mocks.verify(mockList, mocks.atLeastOnce())).add('bob');
System.Assert.fail('an exception was expected because we are asserting that the method is called at least once when instead is never called');
}
catch(fflib_ApexMocks.ApexMocksException ex)
{
System.Assert.areEqual('EXPECTED COUNT: 1 or more times'
+ '\nACTUAL COUNT: 0'
+ '\nMETHOD: fflib_MyList__sfdc_ApexStub.add(String)'
+ '\n---'
+ '\nACTUAL ARGS: ("rob"), ("fred")'
+ '\n---'
+ '\nEXPECTED ARGS: "bob"',
ex.getmessage(),
'Unexpected verify fail message');
}
}
@isTest
private static void thatVerifiesAtLeastOnceNumberOfTimesWithMatchers()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred', 'fred', 'fred', 'fred');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.atLeastOnce())).add(fflib_Match.anyString());
}
@isTest
private static void thatVerifiesAtLeastOnceNumberOfTimesWhenIsCalledMoreTimesWithMatchers()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred', 'fred', 'fred', 'fred');
mockList.add('bob');
mockList.add('fred', 'fred', 'fred', 'fred');
mockList.add('bob');
mockList.add('fred', 'fred', 'fred', 'fred');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.atLeastOnce())).add(fflib_Match.anyString());
}
@isTest
private static void thatThrownExceptionIfCalledLessThanAtLeastOnceNumberOfTimesWithMatchers()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('fred', 'fred', 'fred', 'fred');
mockList.add('fred', 'fred', 'fred', 'fred');
mockList.add('fred', 'fred', 'fred', 'fred');
// Then
try
{
((fflib_MyList.IList) mocks.verify(mockList, mocks.atLeastOnce())).add(fflib_Match.anyString());
System.Assert.fail('an exception was expected because we are asserting that the method is called at lest once when instead is never called');
}
catch(fflib_ApexMocks.ApexMocksException ex)
{
System.Assert.areEqual('EXPECTED COUNT: 1 or more times'
+ '\nACTUAL COUNT: 0'
+ '\nMETHOD: fflib_MyList__sfdc_ApexStub.add(String)'
+ '\n---'
+ '\nACTUAL ARGS: ()'
+ '\n---'
+ '\nEXPECTED ARGS: [any String]',
ex.getMessage(),
'Unexpected verify fail message');
}
}
/*
* between
*/
@isTest
private static void thatVerifiesBetweenNumberOfTimes()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
mockList.add('bob');
mockList.add('fred');
mockList.add('bob');
mockList.add('fred');
mockList.add('bob');
mockList.add('fred');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.between(3, 5))).add('bob');
}
@isTest
private static void thatBetweenThrownExceptionIfCalledLessThanAtLeastNumberOfTimes()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
mockList.add('bob');
// Then
try
{
((fflib_MyList.IList) mocks.verify(mockList, mocks.between(3, 5))).add('bob');
System.Assert.fail('an exception was expected because we are asserting that the method is called at least 3 times when instead is called only twice');
}
catch(fflib_ApexMocks.ApexMocksException ex)
{
System.Assert.areEqual('EXPECTED COUNT: 3 or more times'
+ '\nACTUAL COUNT: 2'
+ '\nMETHOD: fflib_MyList__sfdc_ApexStub.add(String)'
+ '\n---'
+ '\nACTUAL ARGS: ("bob"), ("fred"), ("bob")'
+ '\n---'
+ '\nEXPECTED ARGS: "bob"',
ex.getMessage()
);
}
}
@isTest
private static void thatVerifiesBetweenNumberOfTimesWithMatchers()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
mockList.add('fred');
mockList.add('bob');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.between(3, 5))).add(fflib_Match.anyString());
}
@isTest
private static void thatBetweenThrownExceptionIfCalledLessThanAtLeastNumberOfTimesWithMatchers()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
// Then
try
{
((fflib_MyList.IList) mocks.verify(mockList, mocks.between(3, 5))).add(fflib_Match.anyString());
System.Assert.fail('an exception was expected because we are asserting that the method is called 3 times when instead is called only twice');
}
catch(fflib_ApexMocks.ApexMocksException ex)
{
System.Assert.areEqual('EXPECTED COUNT: 3 or more times'
+ '\nACTUAL COUNT: 2'
+ '\nMETHOD: fflib_MyList__sfdc_ApexStub.add(String)'
+ '\n---'
+ '\nACTUAL ARGS: ("bob"), ("fred")'
+ '\n---'
+ '\nEXPECTED ARGS: [any String]',
ex.getMessage()
);
}
}
@isTest
private static void thatBetweenThrownExceptionIfCalledMoreThanAtMostNumberOfTimes()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
mockList.add('fred');
mockList.add('bob');
mockList.add('bob');
mockList.add('bob');
mockList.add('bob');
mockList.add('bob');
mockList.add('fred');
// Then
try
{
((fflib_MyList.IList) mocks.verify(mockList, mocks.between(3, 5))).add('bob');
System.Assert.fail('an exception was expected because we are asserting that the method is called at most 5 times when instead is called six times');
}
catch(fflib_ApexMocks.ApexMocksException ex)
{
System.Assert.areEqual('EXPECTED COUNT: 5 or fewer times'
+ '\nACTUAL COUNT: 6'
+ '\nMETHOD: fflib_MyList__sfdc_ApexStub.add(String)'
+ '\n---'
+ '\nACTUAL ARGS: ("bob"), ("fred"), ("fred"), ("bob"), ("bob"), ("bob"), ("bob"), ("bob"), ("fred")'
+ '\n---'
+ '\nEXPECTED ARGS: "bob"',
ex.getMessage()
);
}
}
@isTest
private static void thatBetweenThrownExceptionIfCalledMoreThanAtMostNumberOfTimesWithMatchers()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
mockList.add('bob');
mockList.add('fred');
mockList.add('fred');
mockList.add('fred');
// Then
try
{
((fflib_MyList.IList) mocks.verify(mockList, mocks.between(3, 5))).add(fflib_Match.anyString());
System.Assert.fail('an exception was expected because we are asserting that the method is called 5 times when instead is called six times');
}
catch(fflib_ApexMocks.ApexMocksException ex)
{
System.Assert.areEqual('EXPECTED COUNT: 5 or fewer times'
+ '\nACTUAL COUNT: 6'
+ '\nMETHOD: fflib_MyList__sfdc_ApexStub.add(String)'
+ '\n---'
+ '\nACTUAL ARGS: ("bob"), ("fred"), ("bob"), ("fred"), ("fred"), ("fred")'
+ '\n---'
+ '\nEXPECTED ARGS: [any String]',
ex.getMessage(),
'Unexpected verify fail message');
}
}
/*
* never
*/
@isTest
private static void verifyNeverMethodHasNotBeenCalled()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob1');
mockList.add('bob2');
mockList.add('bob3');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.never())).add('bob');
}
@isTest
private static void verifyNeverMethodHasBeenNotCalledWithMatchers()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('fred', 'fred', 'fred', 'fred');
mockList.add('fred', 'fred', 'fred', 'fred');
mockList.add('fred', 'fred', 'fred', 'fred');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.never())).add(fflib_Match.anyString());
}
@isTest
private static void thatVerifyNeverFailsWhenCalledMoreTimes()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('bob');
// Then
try
{
((fflib_MyList.IList) mocks.verify(mockList, mocks.never())).add('bob');
System.Assert.fail('an exception was expected');
}
catch(Exception exc)
{
assertFailMessage(exc.getMessage(), 0, 2);
}
}
@isTest
private static void thatVerifyNeverFailsWhenCalledMoreTimesWithMatchers()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('bob');
mockList.add('bob');
// Then
try
{
((fflib_MyList.IList) mocks.verify(mockList, mocks.never())).add(fflib_Match.anyString());
System.Assert.fail('an exception was expected');
}
catch(Exception exc)
{
assertFailMessage(exc.getMessage(), 0, 3);
}
}
/*
* atLeastOnce
*/
@isTest
private static void thatVerifiesAtLeastOnce()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
mockList.add('bob');
mockList.add('bob');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.atLeastOnce())).add('bob');
}
@isTest
private static void thatVerifiesAtLeastOnceWhenIsCalledMoreTimes()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
mockList.add('bob');
mockList.add('fred');
mockList.add('bob');
mockList.add('fred');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.atLeastOnce())).add('bob');
}
@isTest
private static void thatThrownExceptionIfCalledLessThanAtLeastOnce()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
mockList.add('bob');
// Then
try
{
((fflib_MyList.IList) mocks.verify(mockList, mocks.atLeastOnce())).add('rob');
System.Assert.fail('an exception was expected because we are asserting that the method is called one times when instead is not called');
}
catch(fflib_ApexMocks.ApexMocksException ex)
{
System.Assert.areEqual('EXPECTED COUNT: 1 or more times'
+ '\nACTUAL COUNT: 0'
+ '\nMETHOD: fflib_MyList__sfdc_ApexStub.add(String)'
+ '\n---'
+ '\nACTUAL ARGS: ("bob"), ("fred"), ("bob")'
+ '\n---'
+ '\nEXPECTED ARGS: "rob"',
ex.getMessage(),
'Unexpected verify fail message');
}
}
@isTest
private static void thatVerifiesAtLeastOnceWithMatchers()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.atLeastOnce())).add(fflib_Match.anyString());
}
@isTest
private static void thatVerifiesAtLeastOnceWhenIsCalledMoreTimesWithMatchers()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
mockList.add('fred');
mockList.add('fred');
// Then
((fflib_MyList.IList) mocks.verify(mockList, mocks.atLeastOnce())).add(fflib_Match.anyString());
}
@isTest
private static void thatThrownExceptionIfCalledLessThanAtLeastOnceWithMatchers()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
// Then
try
{
((fflib_MyList.IList) mocks.verify(mockList, mocks.atLeastOnce())).add(fflib_Match.stringStartsWith('rob'));
System.Assert.fail('an exception was expected because we are asserting that the method is called once when instead is not called');
}
catch(fflib_ApexMocks.ApexMocksException ex)
{
System.Assert.areEqual('EXPECTED COUNT: 1 or more times'
+ '\nACTUAL COUNT: 0'
+ '\nMETHOD: fflib_MyList__sfdc_ApexStub.add(String)'
+ '\n---'
+ '\nACTUAL ARGS: ("bob"), ("fred")'
+ '\n---'
+ '\nEXPECTED ARGS: [starts with "rob"]',
ex.getMessage(),
'Unexpected verify fail message');
}
}
/*
* HELPER METHODS
*/
private static void assertFailMessage(String exceptionMessage, Integer expectedInvocations, Integer actualsInvocations)
{
System.Assert.isTrue(
exceptionMessage.startsWith('EXPECTED COUNT: ' + expectedInvocations + '\nACTUAL COUNT: ' + actualsInvocations),
'Unexpected verify fail message: ' + exceptionMessage
);
}
/*
* HELPER CLASSES
*/
private class isOdd implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg instanceof Integer ? Math.mod((Integer)arg, 2) == 1: false;
}
}
private class isEven implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg instanceof Integer ? Math.mod((Integer)arg, 2) == 0: false;
}
}
}
================================================
FILE: sfdx-source/apex-mocks/test/classes/fflib_AnyOrderTest.cls-meta.xml
================================================
63.0
Active
================================================
FILE: sfdx-source/apex-mocks/test/classes/fflib_ApexMocksTest.cls
================================================
/*
* Copyright (c) 2014-2017 FinancialForce.com, inc. All rights reserved.
*/
@isTest
private class fflib_ApexMocksTest
{
private static final fflib_ApexMocks MY_MOCKS = new fflib_ApexMocks();
private static final fflib_MyList MY_MOCK_LIST = (fflib_MyList)MY_MOCKS.mock(fflib_MyList.class);
@isTest
static void whenStubMultipleCallsWithMatchersShouldReturnExpectedValues()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(mockList.get2(fflib_Match.anyInteger(), fflib_Match.anyString())).thenReturn('any');
mocks.when(mockList.get2(fflib_Match.anyInteger(), fflib_Match.stringContains('Hello'))).thenReturn('hello');
mocks.stopStubbing();
// When
String actualValue = mockList.get2(0, 'Hi hi Hello Hi hi');
// Then
System.Assert.areEqual('hello', actualValue);
}
@isTest
static void whenVerifyMultipleCallsWithMatchersShouldReturnCorrectMethodCallCounts()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
// Then
((fflib_MyList.IList) mocks.verify(mockList, 2)).add(fflib_Match.anyString());
((fflib_MyList.IList) mocks.verify(mockList)).add('fred');
((fflib_MyList.IList) mocks.verify(mockList)).add(fflib_Match.stringContains('fred'));
}
@isTest
static void whenStubExceptionWithMatchersShouldThrowException()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
((fflib_MyList.IList) mocks.doThrowWhen(new MyException('Matcher Exception'), mockList)).add(fflib_Match.stringContains('Hello'));
mocks.stopStubbing();
// When
mockList.add('Hi');
try
{
mockList.add('Hi Hello Hi');
System.Assert.fail('Expected exception');
}
catch (MyException e)
{
//Then
System.Assert.areEqual('Matcher Exception', e.getMessage());
}
}
@isTest
static void whenVerifyWithCombinedMatchersShouldReturnCorrectMethodCallCounts()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
// Then
((fflib_MyList.IList) mocks.verify(mockList, 0)).add(
(String)fflib_Match.allOf(fflib_Match.eq('bob'), fflib_Match.stringContains('re'))
);
((fflib_MyList.IList) mocks.verify(mockList)).add(
(String)fflib_Match.allOf(fflib_Match.eq('fred'), fflib_Match.stringContains('re'))
);
((fflib_MyList.IList) mocks.verify(mockList, 2)).add(
(String)fflib_Match.anyOf(fflib_Match.eq('bob'), fflib_Match.eq('fred'))
);
((fflib_MyList.IList) mocks.verify(mockList, 1)).add(
(String)fflib_Match.anyOf(fflib_Match.eq('bob'), fflib_Match.eq('jack'))
);
((fflib_MyList.IList) mocks.verify(mockList, 2)).add(
(String)fflib_Match.noneOf(fflib_Match.eq('jack'), fflib_Match.eq('tim'))
);
((fflib_MyList.IList) mocks.verify(mockList, 2)).add(
(String)fflib_Match.noneOf(
fflib_Match.anyOf(fflib_Match.eq('jack'), fflib_Match.eq('jill')),
fflib_Match.allOf(fflib_Match.eq('tim'), fflib_Match.stringContains('i'))
)
);
((fflib_MyList.IList) mocks.verify(mockList, 2)).add(
(String)fflib_Match.isNot(fflib_Match.eq('jack'))
);
}
@isTest
static void whenStubCustomMatchersCanBeUsed()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(mockList.get((Integer)fflib_Match.matches(new isOdd()))).thenReturn('Odd');
mocks.when(mockList.get((Integer)fflib_Match.matches(new isEven()))).thenReturn('Even');
mocks.stopStubbing();
// When
String s1 = mockList.get(1);
String s2 = mockList.get(2);
String s3 = mockList.get(3);
String s4 = mockList.get(4);
String s5 = mockList.get(5);
// Then
System.Assert.areEqual('Odd', s1);
System.Assert.areEqual('Even', s2);
System.Assert.areEqual('Odd', s3);
System.Assert.areEqual('Even', s4);
System.Assert.areEqual('Odd', s5);
}
@isTest
static void whenVerifyCustomMatchersCanBeUsed()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.get(1);
mockList.get(2);
mockList.get(3);
mockList.get(4);
mockList.get(5);
// Then
((fflib_MyList.IList) mocks.verify(mockList, 3)).get((Integer)fflib_Match.matches(new isOdd()));
((fflib_MyList.IList) mocks.verify(mockList, 2)).get((Integer)fflib_Match.matches(new isEven()));
}
@isTest
static void whenStubWithMatcherAndNonMatcherArgumentsShouldThrowException()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
String expectedError = 'The number of matchers defined (1).'
+ ' does not match the number expected (2)\n'
+ 'If you are using matchers all arguments must be passed in as matchers.\n'
+ 'For example myList.add(fflib_Match.anyInteger(), \'String\') should be defined as myList.add(fflib_Match.anyInteger(), fflib_Match.eq(\'String\')).';
// Then
try
{
mocks.startStubbing();
mocks.when(mockList.get2(fflib_Match.anyInteger(), 'String literal')).thenReturn('fail');
System.Assert.fail('Expected exception');
}
catch (fflib_ApexMocks.ApexMocksException e)
{
System.Assert.areEqual(expectedError, e.getMessage());
}
}
@isTest
static void whenVerifyWithMatcherAndNonMatcherArgumentsShouldThrowException()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
String expectedError = 'The number of matchers defined (1).'
+ ' does not match the number expected (2)\n'
+ 'If you are using matchers all arguments must be passed in as matchers.\n'
+ 'For example myList.add(fflib_Match.anyInteger(), \'String\') should be defined as myList.add(fflib_Match.anyInteger(), fflib_Match.eq(\'String\')).';
mockList.get2(1, 'String literal');
// Then
try
{
((fflib_MyList.IList) mocks.verify(mockList)).get2(fflib_Match.anyInteger(), 'String literal');
System.Assert.fail('Expected exception');
}
catch (fflib_ApexMocks.ApexMocksException e)
{
System.Assert.areEqual(expectedError, e.getMessage());
}
}
@isTest
static void whenStubSameMethodWithMatchersAndNonMatchersShouldStubInOrder()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(mockList.get2(1, 'Non-matcher first')).thenReturn('Bad'); //Set the return value using the non-matcher arguments
mocks.when(mockList.get2(fflib_Match.eqInteger(1), fflib_Match.stringContains('Non-matcher first'))).thenReturn('Good'); //Override the return value using matcher arguments
mocks.when(mockList.get2(fflib_Match.eqInteger(1), fflib_Match.stringContains('Matcher first'))).thenReturn('Bad'); //Set the return value using the matcher arguments
mocks.when(mockList.get2(1, 'Matcher first')).thenReturn('Good'); //Override the return value using non-matcher arguments
mocks.stopStubbing();
// When/Thens
System.Assert.areEqual('Good', mockList.get2(1, 'Non-matcher first'));
System.Assert.areEqual('Good', mockList.get2(1, 'Matcher first'));
}
@isTest
static void whenStubExceptionSameMethodWithMatchersAndNonMatchersShouldStubInOrder()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
((fflib_MyList.IList)mocks.doThrowWhen(new fflib_ApexMocks.ApexMocksException('Bad'), mockList)).add('Non-matcher first'); //Set the exception value using the non-matcher arguments
((fflib_MyList.IList)mocks.doThrowWhen(new fflib_ApexMocks.ApexMocksException('Good'), mockList)).add(fflib_Match.stringContains('Non-matcher first')); //Override the exception value using matcher arguments
((fflib_MyList.IList)mocks.doThrowWhen(new fflib_ApexMocks.ApexMocksException('Bad'), mockList)).add(fflib_Match.stringContains('Matcher first')); //Set the exception value using the matcher arguments
((fflib_MyList.IList)mocks.doThrowWhen(new fflib_ApexMocks.ApexMocksException('Good'), mockList)).add('Matcher first'); //Override the exception value using non-matcher arguments
mocks.stopStubbing();
// When/Thens
try
{
mockList.add('Non-matcher first');
System.Assert.fail('Expected exception');
}
catch (fflib_ApexMocks.ApexMocksException e)
{
System.Assert.areEqual('Good', e.getMessage());
}
try
{
mockList.add('Matcher first');
System.Assert.fail('Expected exception');
}
catch (fflib_ApexMocks.ApexMocksException e)
{
System.Assert.areEqual('Good', e.getMessage());
}
}
@isTest
static void whenStubSingleCallWithSingleArgumentShouldReturnStubbedValue()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(mockList.get(0)).thenReturn('bob');
mocks.stopStubbing();
// When
String actualValue = mockList.get(0);
// Then
System.Assert.areEqual('bob', actualValue);
}
@isTest
static void whenStubSingleCallWithNullReturnValueItShouldReturnNull()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(mockList.get(0)).thenReturn(null);
mocks.stopStubbing();
// When
String actualValue = mockList.get(0);
// Then
System.Assert.areEqual(null, actualValue);
}
@isTest
static void whenStubMultipleCallsWithSingleArgumentShouldReturnStubbedValues()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(mockList.get(0)).thenReturn('bob');
mocks.when(mockList.get(1)).thenReturn('fred');
mocks.stopStubbing();
// When
String actualValueArg0 = mockList.get(0);
String actualValueArg1 = mockList.get(1);
String actualValueArg2 = mockList.get(2);
// Then
System.Assert.areEqual('bob', actualValueArg0);
System.Assert.areEqual('fred', actualValueArg1);
System.Assert.areEqual(null, actualValueArg2);
}
@isTest
static void whenStubSameCallWithDifferentArgumentValueShouldReturnLastStubbedValue()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(mockList.get(0)).thenReturn('bob1');
mocks.when(mockList.get(0)).thenReturn('bob2');
mocks.stopStubbing();
// When
String actualValue = mockList.get(0);
// Then
System.Assert.areEqual('bob2', actualValue);
}
@isTest
static void whenStubCallWithNoArgumentsShouldReturnStubbedValue()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(mockList.isEmpty()).thenReturn(false);
mocks.stopStubbing();
// When
Boolean actualValue = mockList.isEmpty();
// Then
System.Assert.areEqual(false, actualValue);
}
@isTest
static void verifySingleMethodCallWithNoArguments()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.isEmpty();
// Then
((fflib_MyList.IList) mocks.verify(mockList)).isEmpty();
}
@isTest
static void verifySingleMethodCallWithSingleArgument()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
// Then
((fflib_MyList.IList) mocks.verify(mockList)).add('bob');
}
@isTest
static void verifyMultipleMethodCallsWithSameSingleArgument()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('bob');
// Then
((fflib_MyList.IList) mocks.verify(mockList, 2)).add('bob');
}
@isTest
static void verifyMultipleMethodCallsWithDifferentSingleArgument()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add('fred');
// Then
((fflib_MyList.IList) mocks.verify(mockList)).add('bob');
((fflib_MyList.IList) mocks.verify(mockList)).add('fred');
}
@isTest
static void verifyMethodCallsWithSameNameButDifferentArgumentTypes()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
mockList.add(new String[] {'bob'});
mockList.add((String)null);
mockList.add((String[])null);
// Then
((fflib_MyList.IList) mocks.verify(mockList)).add('bob');
((fflib_MyList.IList) mocks.verify(mockList)).add(new String[] {'bob'});
((fflib_MyList.IList) mocks.verify(mockList)).add((String)null);
((fflib_MyList.IList) mocks.verify(mockList)).add((String[])null);
}
@isTest
static void verifyMethodNotCalled()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.get(0);
// Then
((fflib_MyList.IList) mocks.verify(mockList, fflib_ApexMocks.NEVER)).add('bob');
((fflib_MyList.IList) mocks.verify(mockList)).get(0);
}
@isTest
static void stubAndVerifyMethodCallsWithNoArguments()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(mockList.isEmpty()).thenReturn(false);
mocks.stopStubbing();
mockList.clear();
// When
Boolean actualValue = mockList.isEmpty();
// Then
System.Assert.areEqual(false, actualValue);
((fflib_MyList.IList) mocks.verify(mockList)).clear();
}
@isTest
static void whenStubExceptionTheExceptionShouldBeThrown()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(mockList.get(0)).thenThrow(new MyException('Stubbed exception.'));
mocks.stopStubbing();
// When
try
{
mockList.get(0);
System.Assert.fail('Stubbed exception should have been thrown.');
}
catch(Exception e)
{
// Then
System.Assert.isInstanceOfType(e, MyException.class);
System.Assert.areEqual('Stubbed exception.', e.getMessage());
}
}
@isTest
static void whenStubVoidMethodWithExceptionThenExceptionShouldBeThrown()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
((fflib_MyList.IList) mocks.doThrowWhen(new MyException('Stubbed exception.'), mockList)).clear();
mocks.stopStubbing();
// When
try
{
mockList.clear();
System.Assert.fail('Stubbed exception should have been thrown.');
}
catch(Exception e)
{
// Then
System.Assert.isInstanceOfType(e, MyException.class);
System.Assert.areEqual('Stubbed exception.', e.getMessage());
}
}
@isTest
static void whenStubMultipleVoidMethodsWithExceptionsThenExceptionsShouldBeThrown()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
((fflib_MyList.IList) mocks.doThrowWhen(new MyException('clear stubbed exception.'), mockList)).clear();
((fflib_MyList.IList) mocks.doThrowWhen(new MyException('add stubbed exception.'), mockList)).add('bob');
mocks.stopStubbing();
// When
try
{
mockList.clear();
System.Assert.fail('Stubbed exception should have been thrown.');
}
catch(Exception e)
{
// Then
System.Assert.isInstanceOfType(e, MyException.class);
System.Assert.areEqual('clear stubbed exception.', e.getMessage());
}
// When
try
{
mockList.add('bob');
System.Assert.fail('Stubbed exception should have been thrown.');
}
catch(Exception e)
{
// Then
System.Assert.isInstanceOfType(e, MyException.class);
System.Assert.areEqual('add stubbed exception.', e.getMessage());
}
}
@isTest
static void whenStubVoidMethodWithExceptionAndCallMethodTwiceThenExceptionShouldBeThrownTwice()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
((fflib_MyList.IList) mocks.doThrowWhen(new MyException('clear stubbed exception.'), mockList)).clear();
mocks.stopStubbing();
// When
try
{
mockList.clear();
System.Assert.fail('Stubbed exception should have been thrown.');
}
catch(Exception e)
{
// Then
System.Assert.isInstanceOfType(e, MyException.class);
System.Assert.areEqual('clear stubbed exception.', e.getMessage());
}
// When
try
{
mockList.clear();
System.Assert.fail('Stubbed exception should have been thrown.');
}
catch(Exception e)
{
// Then
System.Assert.isInstanceOfType(e, MyException.class);
System.Assert.areEqual('clear stubbed exception.', e.getMessage());
}
}
@isTest
static void verifyMethodCallWhenNoCallsBeenMadeForType()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// Then
((fflib_MyList.IList) mocks.verify(mockList, fflib_ApexMocks.NEVER)).add('bob');
}
@isTest
static void verifySingleMethodCallWithMultipleArguments()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.set(0, 'bob');
// Then
((fflib_MyList.IList) mocks.verify(mockList)).set(0, 'bob');
((fflib_MyList.IList) mocks.verify(mockList, fflib_ApexMocks.NEVER)).set(0, 'fred');
}
@isTest
static void whenStubMultipleCallsWithMultipleArgumentShouldReturnStubbedValues()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(mockList.get2(0, 'zero')).thenReturn('bob');
mocks.when(mockList.get2(1, 'one')).thenReturn('fred');
mocks.when(mockList.get2(0, 'two')).thenReturn('bob');
mocks.when(mockList.get2(1, 'three')).thenReturn('bub');
mocks.stopStubbing();
// When
String actualValueArg0 = mockList.get2(0, 'zero');
String actualValueArg1 = mockList.get2(1, 'one');
String actualValueArg2 = mockList.get2(0, 'two');
String actualValueArg3 = mockList.get2(1, 'three');
String actualValueArg4 = mockList.get2(0, 'three');
// Then
System.Assert.areEqual('bob', actualValueArg0);
System.Assert.areEqual('fred', actualValueArg1);
System.Assert.areEqual('bob', actualValueArg2);
System.Assert.areEqual('bub', actualValueArg3);
System.Assert.areEqual(null, actualValueArg4);
}
@isTest
static void whenStubNullConcreteArgValueCorrectValueIsReturned()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
String expected = 'hello';
mocks.startStubbing();
mocks.when(mockList.get(null)).thenReturn(expected);
mocks.stopStubbing();
// When
String actual = mockList.get(null);
// Then
System.Assert.areEqual(expected, actual);
}
@isTest
static void whenSetDoThrowWhenExceptionsValuesAreSet()
{
//Given
MyException e = new MyException('Test');
fflib_ApexMocks mocks = new fflib_ApexMocks();
List expsList = new List{e};
//When
mocks.DoThrowWhenExceptions = expsList;
//Then
System.Assert.areEqual(expsList, mocks.DoThrowWhenExceptions);
}
@isTest
static void whenVerifyMethodNeverCalledMatchersAreReset()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
// Then
((fflib_MyList.IList) mocks.verify(mockList, fflib_ApexMocks.NEVER)).get(fflib_Match.anyInteger());
((fflib_MyList.IList) mocks.verify(mockList)).add(fflib_Match.anyString());
}
@isTest
static void whenMockIsGeneratedCanVerify()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('bob');
// Then
((fflib_MyList.IList) mocks.verify(mockList, fflib_ApexMocks.NEVER)).get(fflib_Match.anyInteger());
((fflib_MyList.IList) mocks.verify(mockList)).add('bob');
}
@isTest
static void whenMockIsGeneratedCanStubVerify()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mocks.startStubbing();
mocks.when(mockList.get(1)).thenReturn('One');
mocks.when(mockList.get(fflib_Match.integerMoreThan(2))).thenReturn('>Two');
mocks.stopStubbing();
// Then
System.Assert.areEqual(null, mockList.get(0));
System.Assert.areEqual('One', mockList.get(1));
System.Assert.areEqual(null, mockList.get(2));
System.Assert.areEqual('>Two', mockList.get(3));
}
@isTest
static void whenMockVoidMethodRecordsCallCanVerify()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mocks.mockVoidMethod(
mockList,
'clear',
new List(),
new List()
);
// Then
((fflib_MyList.IList) mocks.verify(mockList, 1)).clear();
}
@isTest
static void thatMultipleInstancesCanBeMockedIndependently()
{
fflib_ApexMocksConfig.HasIndependentMocks = true;
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList first = (fflib_MyList)mocks.mock(fflib_MyList.class);
fflib_MyList second = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(first.get(0)).thenReturn('First');
mocks.when(second.get(0)).thenReturn('Second');
mocks.stopStubbing();
// When
String actual = first.get(0);
// Then
System.Assert.areEqual('First', actual, 'Should have returned stubbed value');
((fflib_MyList)mocks.verify(first)).get(0);
((fflib_MyList)mocks.verify(second, mocks.never())).get(0);
}
@isTest
static void thatMultipleInstancesCanBeMockedDependently()
{
fflib_ApexMocksConfig.HasIndependentMocks = false;
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList first = (fflib_MyList)mocks.mock(fflib_MyList.class);
fflib_MyList second = (fflib_MyList)mocks.mock(fflib_MyList.class);
mocks.startStubbing();
mocks.when(first.get(0)).thenReturn('First');
mocks.when(second.get(0)).thenReturn('Second');
mocks.stopStubbing();
// When
String actual = first.get(0);
// Then
System.Assert.areEqual('Second', actual, 'Should have returned stubbed value');
((fflib_MyList)mocks.verify(first)).get(0);
((fflib_MyList)mocks.verify(second)).get(0);
}
static void thatStubbingCanBeChainedFirstExceptionThenValue()
{
// Given
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrow(new MyException('Stubbed exception.')).thenReturn('One');
MY_MOCKS.stopStubbing();
// Then
assertExceptionMessage('Stubbed exception.');
assertReturnedValue('One');
}
@isTest
static void thatStubbingCanBeChainedFirstValueThenException()
{
// Given
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturn('One').thenThrow(new MyException('Stubbed exception.'));
MY_MOCKS.stopStubbing();
// Then
assertReturnedValue('One');
assertExceptionMessage('Stubbed exception.');
}
@isTest
static void thatStubbingMultipleMethodsCanBeChainedFirstExceptionThenValue()
{
// Given
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrow(new MyException('Stubbed exception.')).thenReturn('One');
MY_MOCKS.when(MY_MOCK_LIST.get2(2, 'Hello.')).thenThrow(new MyException('Stubbed exception2.')).thenReturn('One2');
MY_MOCKS.stopStubbing();
// Then
assertExceptionMessage('Stubbed exception.');
assertReturnedValue('One');
assertExceptionMessageForGet2('Stubbed exception2.');
assertReturnedValueForGet2('One2');
}
@isTest
static void thatStubbingMultipleMethodsCanBeChainedFirstValueThenException()
{
// Given
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturn('One').thenThrow(new MyException('Stubbed exception.'));
MY_MOCKS.when(MY_MOCK_LIST.get2(2, 'Hello.')).thenReturn('One2').thenThrow(new MyException('Stubbed exception2.'));
MY_MOCKS.stopStubbing();
// Then
assertReturnedValue('One');
assertExceptionMessage('Stubbed exception.');
assertReturnedValueForGet2('One2');
assertExceptionMessageForGet2('Stubbed exception2.');
}
@isTest
static void thatStubbingReturnsDifferentValuesForDifferentCalls()
{
// Given
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturnMulti(new List{'One', 'Two', 'Three'});
MY_MOCKS.stopStubbing();
// Then
assertReturnedValue('One');
assertReturnedValue('Two');
assertReturnedValue('Three');
}
@isTest
static void thatStubbingReturnsDifferentValuesForDifferentCallsAndRepeatLastValuesForFurtherCalls()
{
// Given
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturnMulti(new List{'One', 'Two', 'Three'});
MY_MOCKS.stopStubbing();
// Then
assertReturnedValue('One');
assertReturnedValue('Two');
assertReturnedValue('Three');
assertReturnedValue('Three');
assertReturnedValue('Three');
}
@isTest
static void thatStubbingThrowsDifferentExceptionsForDifferentCalls()
{
// Given
MyException first = new MyException('first.');
MyException second = new MyException('second.');
MyException third = new MyException('third.');
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrowMulti(new List{first, second, third});
MY_MOCKS.stopStubbing();
// Then
assertExceptionMessage('first.');
assertExceptionMessage('second.');
assertExceptionMessage('third.');
}
@isTest
static void thatStubbingThrowsDifferentExceptionsForDifferentCallsAndRepeatLastExceptionForFurtherCalls()
{
// Given
MyException first = new MyException('first.');
MyException second = new MyException('second.');
MyException third = new MyException('third.');
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrowMulti(new List{first, second, third});
MY_MOCKS.stopStubbing();
// Then
assertExceptionMessage('first.');
assertExceptionMessage('second.');
assertExceptionMessage('third.');
assertExceptionMessage('third.');
assertExceptionMessage('third.');
}
@isTest
static void thatStubbingThrowsAndReturnsDifferentExceptionsAndValuesForDifferentCalls()
{
// Given
MyException first = new MyException('first.');
MyException second = new MyException('second.');
MyException third = new MyException('third.');
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).
thenThrowMulti(new List{first, second, third}).
thenReturnMulti(new List{'One', 'Two', 'Three'});
MY_MOCKS.stopStubbing();
// Then
assertExceptionMessage('first.');
assertExceptionMessage('second.');
assertExceptionMessage('third.');
assertReturnedValue('One');
assertReturnedValue('Two');
assertReturnedValue('Three');
assertReturnedValue('Three');
assertReturnedValue('Three');
}
@isTest
static void thatStubbingReturnsAndThrowsDifferentValuesAndExceptionsForDifferentCalls()
{
// Given
MyException first = new MyException('first.');
MyException second = new MyException('second.');
MyException third = new MyException('third.');
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).
thenReturnMulti(new List{'One', 'Two', 'Three'}).
thenThrowMulti(new List{first, second, third});
MY_MOCKS.stopStubbing();
// Then
assertReturnedValue('One');
assertReturnedValue('Two');
assertReturnedValue('Three');
assertExceptionMessage('first.');
assertExceptionMessage('second.');
assertExceptionMessage('third.');
assertExceptionMessage('third.');
assertExceptionMessage('third.');
}
@isTest
static void thatStubbingMultipleTimesOverridePreviousThenReturnWithSingleValue()
{
// Given
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturn('One');
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturn('Two');
MY_MOCKS.stopStubbing();
// Then
assertReturnedValue('Two');
assertReturnedValue('Two');
}
@isTest
static void thatStubbingMultipleTimesOverridePreviousThenReturnMultiWithSingleValue()
{
// Given
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturnMulti(new List{'One', 'Two', 'Three'});
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturn('Two');
MY_MOCKS.stopStubbing();
// Then
assertReturnedValue('Two');
assertReturnedValue('Two');
}
@isTest
static void thatStubbingMultipleTimesOverridePreviousThenReturnMultiWithMultiValue()
{
// Given
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturnMulti(new List{'One', 'Two', 'Three'});
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturnMulti(new List{'Four', 'Five', 'Six'});
MY_MOCKS.stopStubbing();
// Then
assertReturnedValue('Four');
assertReturnedValue('Five');
assertReturnedValue('Six');
assertReturnedValue('Six');
assertReturnedValue('Six');
}
@isTest
static void thatStubbingMultipleTimesOverridePreviousThenReturnWithMultiValues()
{
// Given
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturn('Two');
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturnMulti(new List{'One', 'Two', 'Three'});
MY_MOCKS.stopStubbing();
// Then
assertReturnedValue('One');
assertReturnedValue('Two');
assertReturnedValue('Three');
assertReturnedValue('Three');
assertReturnedValue('Three');
}
@isTest
static void thatStubbingMultipleTimesOverridePreviousThenReturnMultiWithSingleException()
{
// Given
MyException first = new MyException('first.');
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturnMulti(new List{'One', 'Two', 'Three'});
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrow(first);
MY_MOCKS.stopStubbing();
// Then
assertExceptionMessage('first.');
assertExceptionMessage('first.');
}
@isTest
static void thatStubbingMultipleTimesOverridePreviousThenReturnMultiWithMultiExceptions()
{
// Given
MyException first = new MyException('first.');
MyException second = new MyException('second.');
MyException third = new MyException('third.');
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturnMulti(new List{'One', 'Two', 'Three'});
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrowMulti(new List{first, second, third});
MY_MOCKS.stopStubbing();
// Then
assertExceptionMessage('first.');
assertExceptionMessage('second.');
assertExceptionMessage('third.');
assertExceptionMessage('third.');
assertExceptionMessage('third.');
}
@isTest
static void thatStubbingMultipleTimesOverridePreviousThenReturnWithMultiExceptions()
{
// Given
MyException first = new MyException('first.');
MyException second = new MyException('second.');
MyException third = new MyException('third.');
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturn('Two');
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrowMulti(new List{first, second, third});
MY_MOCKS.stopStubbing();
// Then
assertExceptionMessage('first.');
assertExceptionMessage('second.');
assertExceptionMessage('third.');
assertExceptionMessage('third.');
assertExceptionMessage('third.');
}
@isTest
static void thatStubbingMultipleTimesOverridePreviousThenReturnWithSingleException()
{
// Given
MyException first = new MyException('first.');
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturn('Two');
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrow(first);
MY_MOCKS.stopStubbing();
// Then
assertExceptionMessage('first.');
assertExceptionMessage('first.');
}
@isTest
static void thatStubbingMultipleTimesOverridePreviousThenThrowWithSingleValue()
{
// Given
MyException first = new MyException('first.');
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrow(first);
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturn('Two');
MY_MOCKS.stopStubbing();
// Then
assertReturnedValue('Two');
assertReturnedValue('Two');
}
@isTest
static void thatStubbingMultipleTimesOverridePreviousThenThrowMultiWithSingleValue()
{
// Given
MyException first = new MyException('first.');
MyException second = new MyException('second.');
MyException third = new MyException('third.');
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrowMulti(new List{first, second, third});
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturn('Two');
MY_MOCKS.stopStubbing();
// Then
assertReturnedValue('Two');
assertReturnedValue('Two');
}
@isTest
static void thatStubbingMultipleTimesOverridePreviousThenThrowMultiWithMultiValue()
{
// Given
MyException first = new MyException('first.');
MyException second = new MyException('second.');
MyException third = new MyException('third.');
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrowMulti(new List{first, second, third});
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturnMulti(new List{'Four', 'Five', 'Six'});
MY_MOCKS.stopStubbing();
// Then
assertReturnedValue('Four');
assertReturnedValue('Five');
assertReturnedValue('Six');
assertReturnedValue('Six');
assertReturnedValue('Six');
}
@isTest
static void thatStubbingMultipleTimesOverridePreviousThenThrowWithMultiValues()
{
// Given
MyException first = new MyException('first.');
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrow(first);
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturnMulti(new List{'One', 'Two', 'Three'});
MY_MOCKS.stopStubbing();
// Then
assertReturnedValue('One');
assertReturnedValue('Two');
assertReturnedValue('Three');
assertReturnedValue('Three');
assertReturnedValue('Three');
}
@isTest
static void thatStubbingMultipleTimesOverridePreviousThenThrowMultiWithSingleException()
{
// Given
MyException first = new MyException('first.');
MyException second = new MyException('second.');
MyException third = new MyException('third.');
MyException fourth = new MyException('fourth.');
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrowMulti(new List{first, second, third});
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrow(fourth);
MY_MOCKS.stopStubbing();
// Then
assertExceptionMessage('fourth.');
assertExceptionMessage('fourth.');
}
@isTest
static void thatStubbingMultipleTimesOverridePreviousThenThrowMultiWithMultiExceptions()
{
// Given
MyException first = new MyException('first.');
MyException second = new MyException('second.');
MyException third = new MyException('third.');
MyException fourth = new MyException('fourth.');
MyException fifth = new MyException('fifth.');
MyException sixth = new MyException('sixth.');
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrowMulti(new List{first, second, third});
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrowMulti(new List{fourth, fifth, sixth});
MY_MOCKS.stopStubbing();
// Then
assertExceptionMessage('fourth.');
assertExceptionMessage('fifth.');
assertExceptionMessage('sixth.');
assertExceptionMessage('sixth.');
assertExceptionMessage('sixth.');
}
@isTest
static void thatStubbingMultipleTimesOverridePreviousThenThrowWithMultiExceptions()
{
// Given
MyException beforeFirst = new MyException('before first.');
MyException first = new MyException('first.');
MyException second = new MyException('second.');
MyException third = new MyException('third.');
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrow(beforeFirst);
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrowMulti(new List{first, second, third});
MY_MOCKS.stopStubbing();
// Then
assertExceptionMessage('first.');
assertExceptionMessage('second.');
assertExceptionMessage('third.');
assertExceptionMessage('third.');
assertExceptionMessage('third.');
}
@isTest
static void thatStubbingMultipleTimesOverridePreviousThenThrowWithSingleException()
{
// Given
MyException beforeFirst = new MyException('before first.');
MyException first = new MyException('first.');
// When
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrow(beforeFirst);
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrow(first);
MY_MOCKS.stopStubbing();
// Then
assertExceptionMessage('first.');
assertExceptionMessage('first.');
}
@isTest
static void thatVoidMethodThrowsMultipleExceptions()
{
// Given
MyException beforeFirst = new MyException('before first.');
MyException first = new MyException('first.');
MyException second = new MyException('second.');
MyException third = new MyException('third.');
// When
MY_MOCKS.startStubbing();
((fflib_MyList.IList) MY_MOCKS.doThrowWhen(new List{first, second, third}, MY_MOCK_LIST)).add('Hello');
MY_MOCKS.stopStubbing();
// Then
assertExceptionMessageOnVoidMethod('first.');
assertExceptionMessageOnVoidMethod('second.');
assertExceptionMessageOnVoidMethod('third.');
assertExceptionMessageOnVoidMethod('third.');
assertExceptionMessageOnVoidMethod('third.');
}
@isTest
static void thatMultipleVoidMethodsThrowsMultipleExceptions()
{
// Given
MyException first = new MyException('first.');
MyException second = new MyException('second.');
MyException third = new MyException('third.');
MyException first2 = new MyException('first2.');
MyException second2 = new MyException('second2.');
MyException third2 = new MyException('third2.');
// When
MY_MOCKS.startStubbing();
((fflib_MyList.IList) MY_MOCKS.doThrowWhen(new List{first2, second2, third2}, MY_MOCK_LIST)).addMore('Hello');
((fflib_MyList.IList) MY_MOCKS.doThrowWhen(new List{first, second, third}, MY_MOCK_LIST)).add('Hello');
MY_MOCKS.stopStubbing();
// Then
assertExceptionMessageOnVoidMethod('first.');
assertExceptionMessageOnVoidMethod('second.');
assertExceptionMessageOnVoidMethod('third.');
assertExceptionMessageOnVoidMethod('third.');
assertExceptionMessageOnVoidMethod('third.');
assertExceptionMessageOnAddMoreVoidMethod('first2.');
assertExceptionMessageOnAddMoreVoidMethod('second2.');
assertExceptionMessageOnAddMoreVoidMethod('third2.');
assertExceptionMessageOnAddMoreVoidMethod('third2.');
assertExceptionMessageOnAddMoreVoidMethod('third2.');
}
@isTest
static void thatStubbingMutipleTimesVoidMethodThrowsMultipleExceptionsOverride()
{
// Given
MyException beforeFirst = new MyException('before first.');
MyException first = new MyException('first.');
MyException second = new MyException('second.');
MyException third = new MyException('third.');
MyException fourth = new MyException('fourth.');
MyException fifth = new MyException('fifth.');
MyException sixth = new MyException('sixth.');
// When
MY_MOCKS.startStubbing();
((fflib_MyList.IList) MY_MOCKS.doThrowWhen(new List{first, second, third}, MY_MOCK_LIST)).add('Hello');
((fflib_MyList.IList) MY_MOCKS.doThrowWhen(new List{fourth, fifth, sixth}, MY_MOCK_LIST)).add('Hello');
MY_MOCKS.stopStubbing();
// Then
assertExceptionMessageOnVoidMethod('fourth.');
assertExceptionMessageOnVoidMethod('fifth.');
assertExceptionMessageOnVoidMethod('sixth.');
assertExceptionMessageOnVoidMethod('sixth.');
assertExceptionMessageOnVoidMethod('sixth.');
}
@isTest
static void thatStubbingMutipleTimesVoidMethodThrowsMultipleExceptionsOverrideWithSingleException()
{
// Given
MyException beforeFirst = new MyException('before first.');
MyException first = new MyException('first.');
MyException second = new MyException('second.');
MyException third = new MyException('third.');
MyException fourth = new MyException('fourth.');
MyException fifth = new MyException('fifth.');
MyException sixth = new MyException('sixth.');
// When
MY_MOCKS.startStubbing();
((fflib_MyList.IList) MY_MOCKS.doThrowWhen(new List{first, second, third}, MY_MOCK_LIST)).add('Hello');
((fflib_MyList.IList) MY_MOCKS.doThrowWhen(fourth, MY_MOCK_LIST)).add('Hello');
MY_MOCKS.stopStubbing();
// Then
assertExceptionMessageOnVoidMethod('fourth.');
assertExceptionMessageOnVoidMethod('fourth.');
}
@isTest
static void thatExceptionIsthrownWhenStubbingIsNotDone()
{
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1));
MY_MOCKS.stopStubbing();
try
{
MY_MOCK_LIST.get(1);
System.Assert.fail('an exception was expected');
}
catch(fflib_ApexMocks.ApexMocksException myex)
{
System.Assert.areEqual(
'The stubbing is not correct, no return values have been set.',
myex.getMessage(), 'the message reported by the exception is not correct');
}
}
@isTest
static void thatExceptionIsthrownWhenReturnMultiPassEmptyList()
{
try
{
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturnMulti(new List());
MY_MOCKS.stopStubbing();
System.Assert.fail('an exception was expected');
}
catch(fflib_ApexMocks.ApexMocksException myex)
{
System.Assert.areEqual(
'The stubbing is not correct, no return values have been set.',
myex.getMessage(), 'the message reported by the exception is not correct');
}
}
@isTest
static void thatExceptionIsthrownWhenReturnMultiPassNullList()
{
try
{
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturnMulti(null);
MY_MOCKS.stopStubbing();
System.Assert.fail('an exception was expected');
}
catch(fflib_ApexMocks.ApexMocksException myex)
{
System.Assert.areEqual(
'The stubbing is not correct, no return values have been set.',
myex.getMessage(), 'the message reported by the exception is not correct');
}
}
@isTest
static void thatExceptionIsthrownWhenThrowMultiPassEmptyList()
{
try
{
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrowMulti(new List());
MY_MOCKS.stopStubbing();
System.Assert.fail('an exception was expected');
}
catch(fflib_ApexMocks.ApexMocksException myex)
{
System.Assert.areEqual(
'The stubbing is not correct, no return values have been set.',
myex.getMessage(), 'the message reported by the exception is not correct');
}
}
@isTest
static void thatExceptionIsthrownWhenThrowMultiPassNullList()
{
try
{
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrowMulti(null);
MY_MOCKS.stopStubbing();
System.Assert.fail('an exception was expected');
}
catch(fflib_ApexMocks.ApexMocksException myex)
{
System.Assert.areEqual(
'The stubbing is not correct, no return values have been set.',
myex.getMessage(), 'the message reported by the exception is not correct');
}
}
@isTest
static void thatNullCanBeUsedAsReturnValue()
{
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenReturn(null);
MY_MOCKS.stopStubbing();
System.Assert.areEqual(null, MY_MOCK_LIST.get(1), 'it should be possible stub using the null value');
}
@isTest
static void thatNullCanBeUsedAsExceptionvalue()
{
MY_MOCKS.startStubbing();
MY_MOCKS.when(MY_MOCK_LIST.get(1)).thenThrow(null);
MY_MOCKS.stopStubbing();
System.Assert.areEqual(null, MY_MOCK_LIST.get(1), 'it should be possible stub using the null value');
}
private static void assertExceptionMessage(String expectedMessage)
{
try
{
MY_MOCK_LIST.get(1);
System.Assert.fail('an exception was expected');
}
catch(MyException myex)
{
System.Assert.areEqual(expectedMessage, myex.getMessage(), 'the message reported by the exception is not correct');
}
}
private static void assertExceptionMessageForGet2(String expectedMessage)
{
try
{
MY_MOCK_LIST.get2(2, 'Hello.');
System.Assert.fail('an exception was expected');
}
catch(MyException myex)
{
System.Assert.areEqual(expectedMessage, myex.getMessage(), 'the message reported by the exception is not correct');
}
}
private static void assertExceptionMessageOnVoidMethod(String expectedMessage)
{
try
{
MY_MOCK_LIST.add('Hello');
System.Assert.fail('an exception was expected');
}
catch(MyException myex)
{
System.Assert.areEqual(expectedMessage, myex.getMessage(), 'the message reported by the exception is not correct');
}
}
private static void assertExceptionMessageOnAddMoreVoidMethod(String expectedMessage)
{
try
{
MY_MOCK_LIST.addMore('Hello');
System.Assert.fail('an exception was expected');
}
catch(MyException myex)
{
System.Assert.areEqual(expectedMessage, myex.getMessage(), 'the message reported by the exception is not correct');
}
}
private static void assertReturnedValue(String expectedValue)
{
System.Assert.areEqual(expectedValue, MY_MOCK_LIST.get(1), 'the method did not returned the expected value');
}
private static void assertReturnedValueForGet2(String expectedValue)
{
System.Assert.areEqual(expectedValue, MY_MOCK_LIST.get2(2, 'Hello.'), 'the method did not returned the expected value');
}
@isTest
static void thatToStringReturnsSimpleStringValue()
{
System.Assert.areEqual('fflib_ApexMocks', '' + new fflib_ApexMocks());
}
private class MyException extends Exception
{
}
private class isOdd implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg instanceof Integer ? Math.mod((Integer)arg, 2) == 1: false;
}
}
private class isEven implements fflib_IMatcher
{
public Boolean matches(Object arg)
{
return arg instanceof Integer ? Math.mod((Integer)arg, 2) == 0: false;
}
}
}
================================================
FILE: sfdx-source/apex-mocks/test/classes/fflib_ApexMocksTest.cls-meta.xml
================================================
63.0
Active
================================================
FILE: sfdx-source/apex-mocks/test/classes/fflib_ApexMocksUtilsTest.cls
================================================
/**
* Copyright (c) 2014-2016, FinancialForce.com, inc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the FinancialForce.com, inc nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
@isTest
public class fflib_ApexMocksUtilsTest
{
public static Schema.FieldSet findAnyFieldSet()
{
for (Schema.SObjectType objectType : Schema.getGlobalDescribe().values())
{
for (Schema.FieldSet fs : objectType.getDescribe().FieldSets.getMap().values())
{
return fs;
}
}
return null;
}
@isTest
private static void makeRelationship_returnsObjectsWithRelationFieldSet()
{
//Given
Account acc = new Account(
Id = fflib_IDGenerator.generate(Account.SObjectType),
Name = 'AccName',
NumberOfEmployees = 7
);
Contact contact1 = new Contact(
Id = fflib_IDGenerator.generate(Contact.SObjectType),
DoNotCall = true
);
Contact contact2 = new Contact(
Id = fflib_IDGenerator.generate(Contact.SObjectType),
DoNotCall = false
);
//When
Account accWithRelationships = ((List)fflib_ApexMocksUtils.makeRelationship(
List.class,
new List { acc },
Contact.AccountId,
new List> { new List { contact1, contact2 }}
))[0];
//Then
System.Assert.areEqual(acc.Id, accWithRelationships.Id);
System.Assert.areEqual(acc.Name, accWithRelationships.Name);
System.Assert.areEqual(acc.NumberOfEmployees, accWithRelationships.NumberOfEmployees);
//Assert relationship fields
List contacts = accWithRelationships.Contacts;
System.Assert.areNotEqual(null, contacts);
System.Assert.areEqual(2, contacts.size());
System.Assert.areEqual(contact1.Id, contacts[0].Id);
System.Assert.areEqual(contact1.DoNotCall, contacts[0].DoNotCall);
System.Assert.areEqual(contact2.Id, contacts[1].Id);
System.Assert.areEqual(contact2.DoNotCall, contacts[1].DoNotCall);
}
@isTest
private static void makeRelationship_GenericOverload_ReturnsObjectsWithRelationFieldSet()
{
//Given
SObject acc = Schema.getGlobalDescribe().get('Account').newSObject();
acc.put('Id', fflib_IDGenerator.generate(acc.getSObjectType()));
acc.put('Name', 'AccName');
acc.put('NumberOfEmployees', 7);
SObject contact1 = Schema.getGlobalDescribe().get('Contact').newSObject();
contact1.put('Id', fflib_IDGenerator.generate(contact1.getSObjectType()));
contact1.put('DoNotCall', true);
SObject contact2 = Schema.getGlobalDescribe().get('Contact').newSObject();
contact2.put('Id', fflib_IDGenerator.generate(contact2.getSObjectType()));
contact2.put('DoNotCall', false);
//When
SObject accWithRelationships = ((List)fflib_ApexMocksUtils.makeRelationship(
'Account',
'Contact',
new List { acc },
'AccountId',
new List> { new List { contact1, contact2 }}
))[0];
//Then
System.Assert.areEqual(acc.Id, accWithRelationships.Id);
System.Assert.areEqual(acc.get('Name'), accWithRelationships.get('Name'));
System.Assert.areEqual(acc.get('NumberOfEmployees'), accWithRelationships.get('NumberOfEmployees'));
//Assert relationship fields
List contacts = accWithRelationships.getSObjects('Contacts');
System.Assert.areNotEqual(null, contacts);
System.Assert.areEqual(2, contacts.size());
System.Assert.areEqual(contact1.Id, contacts[0].Id);
System.Assert.areEqual((Boolean)contact1.get('DoNotCall'), (Boolean)contacts[0].get('DoNotCall'));
System.Assert.areEqual(contact2.Id, contacts[1].Id);
System.Assert.areEqual((Boolean)contact2.get('DoNotCall'), (Boolean)contacts[1].get('DoNotCall'));
}
@isTest
private static void makeRelationship_GenericOverload_ThrowsErrorOnInvalidParentType()
{
// Setup parent object
SObject acc = Schema.getGlobalDescribe().get('Account').newSObject();
acc.put('Id', fflib_IDGenerator.generate(acc.getSObjectType()));
// Setup child object
SObject cont = Schema.getGlobalDescribe().get('Contact').newSObject();
cont.put('Id', fflib_IDGenerator.generate(cont.getSObjectType()));
String errorMessage = '';
try {
// Call method under test
SObject accWithRelationships = ((List)fflib_ApexMocksUtils.makeRelationship(
'MyInvalidParentType',
'Contact',
new List { acc },
'AccountId',
new List> { new List { cont }}
))[0];
} catch (Exception exc) {
errorMessage = exc.getMessage();
}
System.Assert.areEqual('SObject type not found: MyInvalidParentType', errorMessage);
}
@isTest
private static void makeRelationship_GenericOverload_ThrowsErrorOnInvalidChildType()
{
// Setup parent object
SObject acc = Schema.getGlobalDescribe().get('Account').newSObject();
acc.put('Id', fflib_IDGenerator.generate(acc.getSObjectType()));
// Setup child object
SObject cont = Schema.getGlobalDescribe().get('Contact').newSObject();
cont.put('Id', fflib_IDGenerator.generate(cont.getSObjectType()));
String errorMessage = '';
try {
// Call method under test
SObject accWithRelationships = ((List)fflib_ApexMocksUtils.makeRelationship(
'Account',
'MyInvalidChildType',
new List { acc },
'AccountId',
new List> { new List { cont }}
))[0];
} catch (Exception exc) {
errorMessage = exc.getMessage();
}
System.Assert.areEqual('SObject type not found: MyInvalidChildType', errorMessage);
}
@isTest
private static void makeRelationship_GenericOverload_ThrowsErrorOnInvalidFieldName()
{
// Setup parent object
SObject acc = Schema.getGlobalDescribe().get('Account').newSObject();
acc.put('Id', fflib_IDGenerator.generate(acc.getSObjectType()));
// Setup child object
SObject cont = Schema.getGlobalDescribe().get('Contact').newSObject();
cont.put('Id', fflib_IDGenerator.generate(cont.getSObjectType()));
String errorMessage = '';
try {
// Call method under test
SObject accWithRelationships = ((List)fflib_ApexMocksUtils.makeRelationship(
'Account',
'Contact',
new List { acc },
'MyInvalidField',
new List> { new List { cont }}
))[0];
} catch (Exception exc) {
errorMessage = exc.getMessage();
}
System.Assert.areEqual('SObject field not found: MyInvalidField', errorMessage);
}
@IsTest
private static void makeRelationship_ObjectWithNull_DoesNotThrowErrorOnJSONExceptionCanNotWriteAFieldNameExpectingAValue()
{
// Given
Product2 prod1 = new Product2(
Id = fflib_IDGenerator.generate(Product2.SObjectType),
Name = 'Product1',
ProductCode = 'P1',
Description = null,
StockKeepingUnit = 'P1'
);
Product2 prod2 = new Product2(
Id = fflib_IDGenerator.generate(Product2.SObjectType),
Name = 'Product2',
ProductCode = 'P2',
Description = 'this is another product',
StockKeepingUnit = 'P2'
);
OpportunityLineItem oli1 = new OpportunityLineItem(
Id = fflib_IDGenerator.generate(OpportunityLineItem.SObjectType),
Product2Id = prod1.Id,
Product2 = prod1,
UnitPrice = 10,
Quantity = 1
);
OpportunityLineItem oli2 = new OpportunityLineItem(
Id = fflib_IDGenerator.generate(OpportunityLineItem.SObjectType),
Product2Id = prod2.Id,
Product2 = prod2,
UnitPrice = 10,
Quantity = 1
);
Opportunity opportunity = new Opportunity();
Exception exceptionThatWasCalled = null;
// When
Test.startTest();
try {
fflib_ApexMocksUtils.makeRelationship(
List.class,
new List{ opportunity },
OpportunityLineItem.OpportunityId,
new List>{ new List{oli1, oli2} }
);
} catch (JSONException e) {
exceptionThatWasCalled = e;
}
Test.stopTest();
// Then
System.debug(exceptionThatWasCalled);
Assert.isNull(exceptionThatWasCalled, 'Exception should not have been called');
}
@isTest
static void setReadOnlyFields_CreatedByIdSetToCurrentUserId_IdFieldSetSuccessfully() {
Account acc = new Account();
Id userId = fflib_IDGenerator.generate((new User()).getSObjectType());
Test.startTest();
acc = (Account)fflib_ApexMocksUtils.setReadOnlyFields(
acc,
Account.class,
new Map{Account.CreatedById => userId}
);
Test.stopTest();
System.Assert.areEqual(userId, acc.CreatedById);
}
@isTest
static void setReadOnlyFields_LastReferencedDateSetOnAccount_DateTimeFieldSetSuccessfully() {
Account acc = new Account();
DateTime lastRefDate = DateTime.newInstanceGmt(2020, 1, 7, 23, 30, 0);
Test.startTest();
acc = (Account)fflib_ApexMocksUtils.setReadOnlyFields(
acc,
Account.class,
new Map {Account.LastReferencedDate => lastRefDate}
);
Test.stopTest();
System.Assert.areEqual(lastRefDate, acc.LastReferencedDate);
}
@isTest
static void setReadOnlyFields_IsDeletedSetOnAccount_BooleanFieldSetSuccessfully() {
Account acc = new Account();
Boolean isDeleted = true;
Test.startTest();
acc = (Account)fflib_ApexMocksUtils.setReadOnlyFields(
acc,
Account.class,
new Map {Account.IsDeleted => isDeleted}
);
Test.stopTest();
System.Assert.areEqual(isDeleted, acc.IsDeleted);
}
@isTest
static void setReadOnlyFields_PolymorphicRelationJoin_FieldSetSuccessfully() {
Account acc = new Account(Name='TestAccount');
Task t = new Task();
Test.startTest();
t = (Task)fflib_ApexMocksUtils.setReadOnlyFields(
t,
Task.class,
new Map {'What' => acc}
);
Test.stopTest();
System.Assert.areEqual(acc.Name, t.What.Name);
}
}
================================================
FILE: sfdx-source/apex-mocks/test/classes/fflib_ApexMocksUtilsTest.cls-meta.xml
================================================
63.0
================================================
FILE: sfdx-source/apex-mocks/test/classes/fflib_ArgumentCaptorTest.cls
================================================
/*
* Copyright (c) 2016-2017 FinancialForce.com, inc. All rights reserved.
*/
/**
* @nodoc
*/
@isTest
private class fflib_ArgumentCaptorTest
{
@isTest
static void thatArgumentValueIsCaptured()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('Fred');
// Then
fflib_ArgumentCaptor argument = fflib_ArgumentCaptor.forClass(String.class);
((fflib_MyList.IList) mocks.verify(mockList)).add((String) argument.capture());
System.Assert.areEqual('Fred', (String)argument.getValue(), 'the argument captured is not as expected');
}
@isTest
static void thatCanPerformFurtherAssertionsOnCapturedArgumentValue()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
//When
TestInnerClass testValue = new TestInnerClass();
testValue.i = 4;
testValue.s = '5';
mockList.set(1, testValue);
//Then
fflib_ArgumentCaptor argument = fflib_ArgumentCaptor.forClass(TestInnerClass.class);
((fflib_MyList.IList) mocks.verify(mockList)).set(fflib_Match.anyInteger(), argument.capture());
Object capturedArg = argument.getValue();
System.Assert.areNotEqual(null, capturedArg, 'CapturedArg should not be null');
System.Assert.isInstanceOfType(capturedArg, TestInnerClass.class, 'CapturedArg should be SObject, instead was ' + capturedArg);
TestInnerClass testValueCaptured = (TestInnerClass)capturedArg;
System.Assert.areEqual(4, testValueCaptured.i, 'the values inside the argument captured should be the same of the original one');
System.Assert.areEqual('5', testValueCaptured.s, 'the values inside the argument captured should be the same of the original one');
}
@isTest
static void thatCaptureArgumentOnlyFromVerifiedMethod()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('Fred');
//the next call should be ignored because is not the method that has under verify,
//even if have the same type specified in the capturer.
mockList.addMore('Barney');
// Then
fflib_ArgumentCaptor argument = fflib_ArgumentCaptor.forClass(String.class);
((fflib_MyList.IList) mocks.verify(mockList)).add((String) argument.capture());
System.Assert.areEqual('Fred', (String)argument.getValue(), 'the argument captured is not as expected');
System.Assert.areEqual(1, argument.getAllValues().size(), 'the argument captured should be only one');
}
@isTest
static void thatCaptureAllArgumentsForTheVerifiedMethods()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
List stringList = new List {'3'};
// When
mockList.add('Fred');
mockList.add(stringList);
mockList.clear();
// Then
fflib_ArgumentCaptor argument = fflib_ArgumentCaptor.forClass(String.class);
((fflib_MyList.IList) mocks.verify(mockList)).add((String) argument.capture());
((fflib_MyList.IList) mocks.verify(mockList)).add((List) argument.capture());
System.Assert.areEqual(stringList, (List)argument.getValue(), 'the argument captured is not as expected');
List argsCaptured = argument.getAllValues();
System.Assert.areEqual(2, argsCaptured.size(), 'expected 2 argument to be captured');
System.Assert.areEqual('Fred', (String) argsCaptured[0], 'the first value is not as expected');
}
@isTest
static void thatCaptureArgumentFromRequestedParameter()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('Fred', 'Barney', 'Wilma', 'Betty');
// Then
fflib_ArgumentCaptor argument = fflib_ArgumentCaptor.forClass(String.class);
((fflib_MyList.IList) mocks.verify(mockList))
.add(
(String) fflib_Match.eq('Fred'),
(String) fflib_Match.eq('Barney'),
(String) argument.capture(),
(String) fflib_Match.eq('Betty'));
System.Assert.areEqual('Wilma', (String)argument.getValue(),
'the argument captured is not as expected, should be Wilma because is the 3rd parameter in the call');
}
@isTest
static void thatCaptureLastArgument()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('Barney');
mockList.add('Fred');
// Then
fflib_ArgumentCaptor argument = fflib_ArgumentCaptor.forClass(String.class);
((fflib_MyList.IList) mocks.verify(mockList, 2)).add((String) argument.capture());
System.Assert.areEqual('Fred', (String)argument.getValue(), 'the argument captured is not as expected');
}
@isTest
static void thatCaptureAllArguments()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('Fred');
mockList.add('Barney');
mockList.add('Wilma');
mockList.add('Betty');
// Then
fflib_ArgumentCaptor argument = fflib_ArgumentCaptor.forClass(String.class);
((fflib_MyList.IList) mocks.verify(mockList, 4)).add((String) argument.capture());
List argsCaptured = argument.getAllValues();
System.Assert.areEqual(4, argsCaptured.size(), 'expected 4 argument to be captured');
System.Assert.areEqual('Fred', (String) argsCaptured[0], 'the first value is not as expected');
System.Assert.areEqual('Barney', (String) argsCaptured[1], 'the second value is not as expected');
System.Assert.areEqual('Wilma', (String) argsCaptured[2], 'the third value is not as expected');
System.Assert.areEqual('Betty', (String) argsCaptured[3], 'the forth value is not as expected');
}
@isTest
static void thatCaptureAllArgumentsFromMultipleMethods()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('Fred');
mockList.add('Barney');
mockList.get2(3, 'pebble');
// Then
fflib_ArgumentCaptor argument = fflib_ArgumentCaptor.forClass(String.class);
((fflib_MyList.IList) mocks.verify(mockList, 2)).add((String) argument.capture());
((fflib_MyList.IList) mocks.verify(mockList))
.get2(
(Integer) fflib_Match.eq(3),
(String) argument.capture());
List argsCaptured = argument.getAllValues();
System.Assert.areEqual(3, argsCaptured.size(), 'expected 3 argument to be captured');
System.Assert.areEqual('Fred', (String) argsCaptured[0], 'the first value is not as expected');
System.Assert.areEqual('Barney', (String) argsCaptured[1], 'the second value is not as expected');
System.Assert.areEqual('pebble', (String) argsCaptured[2], 'the third value is not as expected');
}
@isTest
static void thatCanHandleMultipleCapturesInOneMethodCall()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('Fred', 'Barney', 'Wilma', 'Betty');
// Then
fflib_ArgumentCaptor argument = fflib_ArgumentCaptor.forClass(String.class);
((fflib_MyList.IList) mocks.verify(mockList))
.add(
(String) fflib_Match.eq('Fred'),
(String) argument.capture(),
(String) argument.capture(),
(String) fflib_Match.eq('Betty'));
List argsCaptured = argument.getAllValues();
System.Assert.areEqual(2, argsCaptured.size(), 'expected 2 argument to be captured');
System.Assert.areEqual('Barney', (String) argsCaptured[0], 'the first value is not as expected');
System.Assert.areEqual('Wilma', (String) argsCaptured[1], 'the second value is not as expected');
}
@isTest
static void thatDoesNotCaptureIfNotVerified()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('3');
// Then
fflib_ArgumentCaptor argument = fflib_ArgumentCaptor.forClass(List.class);
((fflib_MyList.IList) mocks.verify(mockList, fflib_ApexMocks.NEVER))
.add((List) argument.capture());
List argsCaptured = argument.getAllValues();
System.Assert.areEqual(0, argsCaptured.size(), 'expected 0 argument to be captured');
System.Assert.areEqual(null, argument.getValue(), 'no value should be captured, so must return null');
}
@isTest
static void thatCaptureOnlyMethodsThatMatchesWithOtherMatcherAsWell()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('Same', 'Same', 'First call', 'First call');
mockList.add('Same', 'Same', 'Second call', 'Second call');
// Then
fflib_ArgumentCaptor argument = fflib_ArgumentCaptor.forClass(String.class);
((fflib_MyList.IList) mocks.verify(mockList)).add(
fflib_Match.eqString('Same'),
fflib_Match.eqString('Same'),
(String)argument.capture(),
fflib_Match.eqString('First call'));
System.Assert.areEqual('First call', (String)argument.getValue());
}
@isTest
static void thatDoesNotCaptureAnythingWhenCaptorIsWrappedInAMatcher()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
// When
mockList.add('Same', 'Same', 'First call', 'First call');
mockList.add('Same', 'Same', 'Second call', 'Second call');
// Then
fflib_ArgumentCaptor argument = fflib_ArgumentCaptor.forClass(String.class);
((fflib_MyList.IList) mocks.verify(mockList)).add(
(String) fflib_Match.allOf(
fflib_Match.eqString('Same'),
fflib_Match.eqString('Same'),
argument.capture()),
(String) fflib_Match.allOf(
fflib_Match.eqString('Same'),
fflib_Match.eqString('Same'),
argument.capture()),
(String) fflib_Match.allOf(
argument.capture(),
fflib_Match.eqString('First call')),
(String) fflib_Match.allOf(
argument.capture(),
fflib_Match.eqString('First call'))
);
List capturedValues = argument.getAllValues();
System.Assert.areEqual(0, capturedValues.size(),
'nothing should have been capture because the matcher it not really a capture type, but a allOf()');
System.Assert.isNull((String)argument.getValue(),
'nothing should have been capture because the matcher it not really a capture type, but a allOf()');
}
@isTest
static void thatArgumentValueIsCapturedWithInOrderVerification()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
fflib_InOrder inOrder1 = new fflib_InOrder(mocks, new List{ mockList });
// When
mockList.add('Fred');
// Then
fflib_ArgumentCaptor argument = fflib_ArgumentCaptor.forClass(String.class);
((fflib_MyList.IList)inOrder1.verify(mockList, mocks.calls(1))).add((String) argument.capture());
System.Assert.areEqual('Fred', (String)argument.getValue(), 'the argument captured is not as expected');
}
@isTest
static void thatCanPerformFurtherAssertionsOnCapturedArgumentValueWithInOrderVerification()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
fflib_InOrder inOrder1 = new fflib_InOrder(mocks, new List{ mockList });
//When
TestInnerClass testValue = new TestInnerClass();
testValue.i = 4;
testValue.s = '5';
mockList.set(1, testValue);
//Then
fflib_ArgumentCaptor argument = fflib_ArgumentCaptor.forClass(TestInnerClass.class);
((fflib_MyList.IList) inOrder1.verify(mockList, mocks.calls(1))).set(fflib_Match.anyInteger(), argument.capture());
Object capturedArg = argument.getValue();
System.Assert.areNotEqual(null, capturedArg, 'CapturedArg should not be null');
System.Assert.isInstanceOfType(capturedArg, TestInnerClass.class, 'CapturedArg should be SObject, instead was ' + capturedArg);
TestInnerClass testValueCaptured = (TestInnerClass)capturedArg;
System.Assert.areEqual(4, testValueCaptured.i, 'the values inside the argument captured should be the same of the original one');
System.Assert.areEqual('5', testValueCaptured.s, 'the values inside the argument captured should be the same of the original one');
}
@isTest
static void thatCaptureArgumentOnlyFromVerifiedMethodWithInOrderVerification()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
fflib_InOrder inOrder1 = new fflib_InOrder(mocks, new List{ mockList });
// When
mockList.add('Fred');
//the next call should be ignored because is not the method that has under verify,
//even if have the same type specified in the capturer.
mockList.addMore('Barney');
// Then
fflib_ArgumentCaptor argument = fflib_ArgumentCaptor.forClass(String.class);
((fflib_MyList.IList) inOrder1.verify(mockList, mocks.calls(1))).add((String) argument.capture());
System.Assert.areEqual('Fred', (String)argument.getValue(), 'the argument captured is not as expected');
System.Assert.areEqual(1, argument.getAllValues().size(), 'the argument captured should be only one');
}
@isTest
static void thatCaptureAllArgumentsForTheVerifiedMethodsWithInOrderVerification()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
fflib_InOrder inOrder1 = new fflib_InOrder(mocks, new List{ mockList });
List stringList = new List {'3'};
// When
mockList.add('Fred');
mockList.add(stringList);
mockList.clear();
// Then
fflib_ArgumentCaptor argument = fflib_ArgumentCaptor.forClass(String.class);
((fflib_MyList.IList) inOrder1.verify(mockList, mocks.calls(1))).add((String) argument.capture());
((fflib_MyList.IList) inOrder1.verify(mockList, mocks.calls(1))).add((List) argument.capture());
System.Assert.areEqual(stringList, (List)argument.getValue(), 'the argument captured is not as expected');
List argsCaptured = argument.getAllValues();
System.Assert.areEqual(2, argsCaptured.size(), 'expected 2 argument to be captured');
System.Assert.areEqual('Fred', (String) argsCaptured[0], 'the first value is not as expected');
}
@isTest
static void thatCaptureArgumentFromRequestedParameterWithInOrderVerification()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
fflib_InOrder inOrder1 = new fflib_InOrder(mocks, new List{ mockList });
// When
mockList.add('Fred', 'Barney', 'Wilma', 'Betty');
// Then
fflib_ArgumentCaptor argument = fflib_ArgumentCaptor.forClass(String.class);
((fflib_MyList.IList) inOrder1.verify(mockList, mocks.calls(1)))
.add(
(String) fflib_Match.eq('Fred'),
(String) fflib_Match.eq('Barney'),
(String) argument.capture(),
(String) fflib_Match.eq('Betty'));
System.Assert.areEqual('Wilma', (String)argument.getValue(),
'the argument captured is not as expected, should be Wilma because is the 3rd parameter in the call');
}
@isTest
static void thatCaptureLastArgumentWithInOrderVerification()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
fflib_InOrder inOrder1 = new fflib_InOrder(mocks, new List{ mockList });
// When
mockList.add('Barney');
mockList.add('Fred');
// Then
fflib_ArgumentCaptor argument = fflib_ArgumentCaptor.forClass(String.class);
((fflib_MyList.IList) inOrder1.verify(mockList, mocks.calls(2))).add((String) argument.capture());
System.Assert.areEqual('Fred', (String)argument.getValue(), 'the argument captured is not as expected');
}
@isTest
static void thatCaptureAllArgumentsWithInOrderVerification()
{
// Given
fflib_ApexMocks mocks = new fflib_ApexMocks();
fflib_MyList mockList = (fflib_MyList)mocks.mock(fflib_MyList.class);
fflib_InOrder inOrder1 = new fflib_InOrder(mocks, new List{ mockList });
// When
mockList.add('Fred');
mockList.add('Barney');
mockList.add('Wilma');
mockList.add('Betty');
// Then
fflib_ArgumentCaptor argument = fflib_ArgumentCaptor.forClass(String.class);
((fflib_MyList.IList) inOrder1.verify(mockList, mocks.calls(4))).add((String) argument.capture());
List