SlideShare a Scribd company logo
Enhanced Web Service Testing
​ Kirk Steffke
​ AppExchange Practice Lead
​ kirk@crmscience.com
​ @kirkevonphilly
​ 
A Better Mock Structure
•  Test Coverage Overview
•  Review of Native Testing Methods
•  WebServiceMock and HttpCalloutMock
Interfaces
•  StaticResourceCalloutMock
•  MultiStaticResourceCalloutMock
•  Sample Scenario
•  Better Mock Structure
•  Setup
•  Review
Agenda
​ During this session
Test Coverage Overview
The who, what, when, where, and why’s of creating coverage
•  Code we write…
•  …about the code we just wrote
•  Test classes
•  Independent of code being tested
•  One or more test methods
•  @isTest annotation
Apex Test Coverage
​ “What” with a Hint of “How”
Apex Test Coverage
​ A Bit More of “How”
Grandma’s Famous Recipe
1.  Write code to do
something
2.  Create test class
3.  Mark with @isTest
4.  Create test method
5.  Create test data
6.  Invoke code being
tested
7.  Assert (+ or -)
•  Code we write…
•  …about the code we just wrote
•  Test classes
•  Independent of code being tested
•  One or more test method
Apex Test Coverage
Now More “What”
•  You, me, everyone
•  Required
•  75%
•  Ongoing Development
•  Help catch regressions
•  Positive and negative assertions
Apex Test Coverage
​ “Who-ot” and “Why”
•  As you’re developing
•  Moving code from sandbox to production
•  Creating packages
Apex Test Coverage
​ When
Native Testing Strategies
The Tools that are Already in your Toolbox
•  Class w/ single method that makes a callout
Sample Scenario: Single Callout
​ Class Needing Coverage
Sample Scenario: Single Callout
​ Class Needing Coverage
​ Gist: https://gist.github.com/KirkSteffke/2ca4357c7e84eece9073
•  Method making callout needs coverage
•  Don’t want test methods to actually make callout!
•  Responses to be used for positive/negative tests
Sample Scenario: Testing Objective
​ What We Need to Test
•  Defined within test class
•  Returns single callout
response
•  WebServiceMock for WSDL
based SOAP callouts
•  HttpCalloutMock for testing
Http callouts
•  Defined by content of text
file in Static Resource
•  Returns response for a
single endpoint
•  Similar to
StaticResourceCalloutMock
•  Static Resource contains
response for multiple
endpoints
WebServiceMock and
HttpCalloutMock Interfaces
StaticResourceCalloutMock
MultiStaticResourceCalloutMo
ck
Documentation: bit.ly/df15mock3Documentation: bit.ly/df15mock1 Documentation: bit.ly/df15mock2
Options for Testing HTTP Callouts
​ Out-of-the-box Tools
•  Defined within test class
•  Returns single callout
response
•  WebServiceMock for WSDL
based SOAP callouts
•  HttpCalloutMock for testing
Http callouts
•  Defined by content of text
file in Static Resource
•  Returns response for a
single endpoint
•  Similar to
StaticResourceCalloutMock
•  Static Resource contains
response for multiple
endpoints
WebServiceMock and
HttpCalloutMock Interfaces
StaticResourceCalloutMock
MultiStaticResourceCalloutMo
ck
Documentation: bit.ly/df15mock3Documentation: bit.ly/df15mock1 Documentation: bit.ly/df15mock2
Options for Testing HTTP Callouts
​ Out-of-the-box Tools
•  Not “the” test, but is @test
•  Called by test class methods
•  Returns “mock” responses
•  Sets up header, body, and status code
HttpCalloutMock Interface
​ Part 1: Mock Responder Class
HttpCalloutMock Interface
​ Part 1: Mock Responder Class
​ Gist: https://gist.github.com/KirkSteffke/0d1f22c77b6d3a2f5599
•  Test class for class making callout (part 1)
•  Utilizes Mock Responder Class (part 2)
•  Respond from callout comes from responder class (part 2)
HttpCalloutMock Interface
​ Part 2: Test Coverage
HttpCalloutMock Interface
​ Part 2: Test Coverage
HttpCalloutMock Interface
​ Recap
•  Defined within test class
•  Returns single callout
response
•  WebServiceMock for WSDL
based SOAP callouts
•  HttpCalloutMock for testing
Http callouts
•  Defined by content of text
file in Static Resource
•  Returns response for a
single endpoint
•  Similar to
StaticResourceCalloutMock
•  Static Resource contains
response for multiple
endpoints
WebServiceMock and
HttpCalloutMock Interfaces
StaticResourceCalloutMock
MultiStaticResourceCalloutMo
ck
Documentation: bit.ly/df15mock3Documentation: bit.ly/df15mock1 Documentation: bit.ly/df15mock2
Options for Testing HTTP Callouts
​ Out-of-the-box Tools
StaticResourceCalloutMock
Part 1: The static resource
•  Only contains JSON text
•  Can’t be a zipped static resource w/ multiple files
•  mock.setStaticResource(‘Name of Zip’,’File in Zip’)
StaticResourceCalloutMock
​ Part 2: Test coverage
•  Slightly different from last example
•  No separate class; defined within coverage
•  StaticResourceCalloutMock object instead of class with HttpCalloutMock interface
StaticResourceCalloutMock
​ Part 2: Test coverage
•  Defined within test class
•  Returns single callout
response
•  WebServiceMock for WSDL
based SOAP callouts
•  HttpCalloutMock for testing
Http callouts
•  Defined by content of text
file in Static Resource
•  Returns response for a
single endpoint
•  Similar to
StaticResourceCalloutMock
•  Static Resource contains
response for multiple
endpoints
WebServiceMock and
HttpCalloutMock Interfaces
StaticResourceCalloutMock
MultiStaticResourceCalloutMo
ck
Documentation: bit.ly/df15mock3Documentation: bit.ly/df15mock1 Documentation: bit.ly/df15mock2
Options for Testing HTTP Callouts
​ Out-of-the-box Tools
•  Two methods making callouts
•  One method using both
MultiStaticResourceCalloutMock
Part 1: Modified Scenario
•  Similar to StaticResourceCalloutMock
•  Define multiple endpoints
•  Each has own Static Resource
•  Still no Zip file
MultiStaticResourceCalloutMock
Part 2: Test Coverage
Static Resource: Example3_bar1 Static Resource: Example3_bar2
MultiStaticResourceCalloutMock
Part 2: Test Coverage
1.  New MultiStaticResourceCalloutMock()
2.  Set endpoint based resources
3.  Set mock
4.  Invoke callouts
5.  Perform assertions
Complex Scenario
A hypothetical, but real-world model to help you digest
•  Batch job
•  Import of Contacts from remote system
•  Remote system has an API
•  Two endpoints
•  /api/ContactCount
•  /api/Contacts
Remote Import via Batch
Overview
•  /api/ContactCount
•  Returns # of Contact records to be imported
•  Result can change during span of batch execution
•  /api/Contacts
•  Returns x number of contacts
•  Paginated
•  Page=1 – returns 1st 200 records
•  Page=2 – returns 2nd 200 records
•  …and so on
Remote Import via Batch
Meet the Endpoints
1.  Batch is called
2.  Start() method
3.  Each execute() iteration performs 2 callouts
4.  1st checks total # of records available
5.  2nd imports records
6.  End of execute determines if more
records?
7.  Execute may run for many iterations
8.  If no more records or limits, finish()
9.  Restart cycle
10.  End
Remote Import via Batch
Batch Flow
Better Mock Structure
Using our tools to make better tools
Limitations
Working with Our Tools
•  HttpCalloutMock Interface and StaticResourceMock
•  Can only handle one endpoint
•  Single response
•  Single setup prior to invoking actual callouts
•  MultiStaticResourceCalloutMock
•  Handle multiple endpoints
•  Single response for each
•  Single setup prior to invoking actual callouts
Problems
Continued…
•  Challenge
•  Use one or more standard tool
•  Extend the usage
•  Create queue of expected responses per endpoint
•  Consider re-usability
•  MakeCallouts Method
•  Loops 10x
•  Builds string of results
•  ContactCount Method
•  Makes Callout
•  Contacts Method
•  Makes callout
•  Page Parameter
Building the Problem
Example4_CalloutClass.apxc
public class Example4_CalloutClass {
// Method to simulate all the callouts in our batch flow
public static string MakeCallouts() {
// Property to return
string results = '';
// Let's call each resource 10x and...
for (integer i = 0; i < 10; i++) {
// ...add to results string this Count's response's body
results += 'Count (' + i + '): ' + CalloutContactCount().getBody() + 'rn';
// ...add to results string this Contact response's body
results += 'Contacts (' + i + '): ' + CalloutContacts(i).getBody() + 'rn';
}
// Return concatenated string of results
return results;
•  ResponseMap
•  By method
•  By endpoint
•  List of responses
•  Respond
•  Verify request
•  Prepare response
•  Discard
•  Resp Class
Building the Solution
TestCalloutResponseGenerator.apxc
@isTest
global class TestCalloutResponseGenerator implements HttpCalloutMock {
// Property and getter (semi init'd) to pair method --> endpoint --> list of responses
private static map<string, map<string, list<resp>>> ResponseMap;
public static map<string, map<string, list<resp>>> getResponseMap() {
if (ResponseMap == null) {
ResponseMap = new map<string, map<string, list<resp>>>();
// For each setMethod() method type, pre-pop. w/ empty map
for (string method :new list<string>{'GET','PUT','POST','DELETE','HEAD','TRACE'})
ResponseMap.put(method, new map<string, list<resp>>());
}
return ResponseMap;
}
// Required respond() method for HttpCalloutMock
public HttpResponse Respond(HttpRequest req) {
•  Body (JSON)
•  Status (success)
•  StatusCode
•  Discard
Building the Solution
TestCalloutResponseGenerator.Resp
// Class to hold details of response from within test methods
public class Resp {
public string body { get; set; }
public string status { get; set; }
public integer statusCode { get; set; }
public boolean discard { get; set; }
public Resp(string body, string status, integer statusCode, boolean discard) {
this.body = body;
this.status = status;
this.statusCode = statusCode;
this.discard = discard;
}
}
•  ResponseMap
•  By method
•  By endpoint
•  List of responses
Building the Solution
TestCalloutResponseGenerator.getResponseMap()
// Property to pair method --> endpoint --> list of responses
private static map<string, map<string, list<resp>>> ResponseMap;
// Getter to return or prepare a semi init'd response map
public static map<string, map<string, list<resp>>> getResponseMap() {
if (ResponseMap == null) {
ResponseMap = new map<string, map<string, list<resp>>>();
// For each setMethod() method type, pre-pop. w/ empty map
for (string method :new list<string>{'GET','PUT','POST','DELETE','HEAD','TRACE'})
ResponseMap.put(method, new map<string, list<resp>>());
}
return ResponseMap;
}
•  Respond
•  Verify request
•  Prepare response
•  Discard
Building the Solution
TestCalloutResponseGenerator.Respond(HttpRequest req)
// Required respond() method for HttpCalloutMock
public HttpResponse Respond(HttpRequest req) {
// Property for returned response
HttpResponse res = new HttpResponse();
// Ensure HttpRequest is valid
if (req != null && !string.isBlank(req.getMethod()) && !string.isBlank(req.getEndPoint())) {
// Verify the Response map contains the req's method and endpoint
if (getResponseMap().containsKey(req.getMethod()) &&
getResponseMap().get(req.getMethod()).containsKey(req.getEndpoint())
) {
// Instantiate a list of the method/endpoint's response bodies
list<resp> respList =
getResponseMap().get(req.getMethod()).get(req.getEndpoint());
// If there's at least one, use it - otherwise, output an error
if (!respList.isEmpty()) {
•  Setup ResponseMap
•  Shortcut Explanation
•  Contacts
•  ContactCount
•  Discard
•  Set mock
•  Invoke Callout
Testing the Solution
Example4_TestCalloutClass.TestWithPattern()
@isTest
public class Example4_TestCalloutClass {
public static testMethod void TestWithPattern() {
/* The below is just a shortcut for the demo. Instead of this 10x (1 per page):
TestCalloutResponseGenerator.getResponseMap().get('GET').put(
'/api/Contacts?page=1',
new list<TestCalloutResponseGenerator.Resp> {
new TestCalloutResponseGenerator.Resp(
'{"Contacts":"data...page 1'"}',
'success',
200,
false
)
}
);
*/
// Temporary collection to hold looped results (for demo, we don't care about actual data,
Testing the Solution
Example4_TestCalloutClass.TestWithPattern()
// Temporary collection to hold looped results (for demo, we don't care about actual data, just proof of concept)
map<string, list<TestCalloutResponseGenerator.Resp>> pagedResponses =
new map<string, list<TestCalloutResponseGenerator.Resp>>();
// Create a dummy response for Contact callout for our "10" pages of contacts
for (integer i = 0; i < 10; i++) {
// Each loop = 1 page
pagedResponses.put('/api/Contacts?page=' + i, new list<TestCalloutResponseGenerator.Resp>{
new TestCalloutResponseGenerator.Resp(
'{"Contacts":"data...' + i + '"}',
'success',
200,
true)
});
}
// Add all of the contact responses to the response map
TestCalloutResponseGenerator.getResponseMap().put('GET', pagedResponses);
•  Setup ResponseMap
•  Shortcut Explanation
•  Contacts
•  ContactCount
•  Discard
•  Set mock
•  Invoke Callout
Testing the Solution
Example4_TestCalloutClass.TestWithPattern()
// Enable mock response
Test.setMock(HttpCalloutMock.class, new TestCalloutResponseGenerator());
// Invoke the callout method
string results = Example4_CalloutClass.MakeCallouts();
system.debug('Results: rnrn' + results);
Testing the Solution
TestCalloutClass
1.  Count or Contact callout
2.  # of loop iteration
3.  Count data 10, 12, 12, …
1.  Use 1st, discard
2.  Use 2nd, don’t discard
4.  Contact data increments
1.  Provided per page response
Thank you

More Related Content

What's hot

Performance testing
Performance testingPerformance testing
Performance testing
Ranpreet kaur
 
Manual testing
Manual testingManual testing
Manual testing
ShahaniIntikab
 
Performance and load testing
Performance and load testingPerformance and load testing
Performance and load testing
sonukalpana
 
Karate - Web-Service API Testing Made Simple
Karate - Web-Service API Testing Made SimpleKarate - Web-Service API Testing Made Simple
Karate - Web-Service API Testing Made Simple
VodqaBLR
 
Automation Testing
Automation TestingAutomation Testing
Automation Testing
Sun Technlogies
 
Chapter 3 - Performance Testing in the Software Lifecycle
Chapter 3 - Performance Testing in the Software LifecycleChapter 3 - Performance Testing in the Software Lifecycle
Chapter 3 - Performance Testing in the Software Lifecycle
Neeraj Kumar Singh
 
Basic Guide to Manual Testing
Basic Guide to Manual TestingBasic Guide to Manual Testing
Basic Guide to Manual Testing
Hiral Gosani
 
Mobile application testing
Mobile application testingMobile application testing
Mobile application testing
Softheme
 
Automation Tools Overview
Automation Tools OverviewAutomation Tools Overview
Automation Tools Overview
Murageppa-QA
 
Software Development Life Cycle – SDLC
Software Development Life Cycle – SDLCSoftware Development Life Cycle – SDLC
Software Development Life Cycle – SDLC
Shwetha-BA
 
Test Automation and Selenium
Test Automation and SeleniumTest Automation and Selenium
Test Automation and Selenium
Karapet Sarkisyan
 
BDD with Cucumber
BDD with CucumberBDD with Cucumber
BDD with Cucumber
Knoldus Inc.
 
Performance testing interview questions and answers
Performance testing interview questions and answersPerformance testing interview questions and answers
Performance testing interview questions and answers
Garuda Trainings
 
Performance Testing And Its Type | Benefits Of Performance Testing
Performance Testing And Its Type | Benefits Of Performance TestingPerformance Testing And Its Type | Benefits Of Performance Testing
Performance Testing And Its Type | Benefits Of Performance Testing
KostCare
 
Test automation wipro
Test automation   wiproTest automation   wipro
Test automation wipro
ambreprasad77
 
Karate DSL
Karate DSLKarate DSL
Karate DSL
anil borse
 
Karate - powerful and simple framework for REST API automation testing
Karate - powerful and simple framework for REST API automation testingKarate - powerful and simple framework for REST API automation testing
Karate - powerful and simple framework for REST API automation testing
Roman Liubun
 
Test Automation Strategies For Agile
Test Automation Strategies For AgileTest Automation Strategies For Agile
Test Automation Strategies For Agile
Naresh Jain
 
Software Testing Process
Software Testing ProcessSoftware Testing Process
Software Testing Process
guest1f2740
 
Load Testing and JMeter Presentation
Load Testing and JMeter PresentationLoad Testing and JMeter Presentation
Load Testing and JMeter Presentation
Neill Lima
 

What's hot (20)

Performance testing
Performance testingPerformance testing
Performance testing
 
Manual testing
Manual testingManual testing
Manual testing
 
Performance and load testing
Performance and load testingPerformance and load testing
Performance and load testing
 
Karate - Web-Service API Testing Made Simple
Karate - Web-Service API Testing Made SimpleKarate - Web-Service API Testing Made Simple
Karate - Web-Service API Testing Made Simple
 
Automation Testing
Automation TestingAutomation Testing
Automation Testing
 
Chapter 3 - Performance Testing in the Software Lifecycle
Chapter 3 - Performance Testing in the Software LifecycleChapter 3 - Performance Testing in the Software Lifecycle
Chapter 3 - Performance Testing in the Software Lifecycle
 
Basic Guide to Manual Testing
Basic Guide to Manual TestingBasic Guide to Manual Testing
Basic Guide to Manual Testing
 
Mobile application testing
Mobile application testingMobile application testing
Mobile application testing
 
Automation Tools Overview
Automation Tools OverviewAutomation Tools Overview
Automation Tools Overview
 
Software Development Life Cycle – SDLC
Software Development Life Cycle – SDLCSoftware Development Life Cycle – SDLC
Software Development Life Cycle – SDLC
 
Test Automation and Selenium
Test Automation and SeleniumTest Automation and Selenium
Test Automation and Selenium
 
BDD with Cucumber
BDD with CucumberBDD with Cucumber
BDD with Cucumber
 
Performance testing interview questions and answers
Performance testing interview questions and answersPerformance testing interview questions and answers
Performance testing interview questions and answers
 
Performance Testing And Its Type | Benefits Of Performance Testing
Performance Testing And Its Type | Benefits Of Performance TestingPerformance Testing And Its Type | Benefits Of Performance Testing
Performance Testing And Its Type | Benefits Of Performance Testing
 
Test automation wipro
Test automation   wiproTest automation   wipro
Test automation wipro
 
Karate DSL
Karate DSLKarate DSL
Karate DSL
 
Karate - powerful and simple framework for REST API automation testing
Karate - powerful and simple framework for REST API automation testingKarate - powerful and simple framework for REST API automation testing
Karate - powerful and simple framework for REST API automation testing
 
Test Automation Strategies For Agile
Test Automation Strategies For AgileTest Automation Strategies For Agile
Test Automation Strategies For Agile
 
Software Testing Process
Software Testing ProcessSoftware Testing Process
Software Testing Process
 
Load Testing and JMeter Presentation
Load Testing and JMeter PresentationLoad Testing and JMeter Presentation
Load Testing and JMeter Presentation
 

Similar to Enhanced Web Service Testing: A Better Mock Structure

Enhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock StructureEnhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock Structure
CRMScienceKirk
 
Developer testing 101: Become a Testing Fanatic
Developer testing 101: Become a Testing FanaticDeveloper testing 101: Become a Testing Fanatic
Developer testing 101: Become a Testing Fanatic
LB Denker
 
Apex Testing and Best Practices
Apex Testing and Best PracticesApex Testing and Best Practices
Apex Testing and Best Practices
Jitendra Zaa
 
Performance Test Driven Development with Oracle Coherence
Performance Test Driven Development with Oracle CoherencePerformance Test Driven Development with Oracle Coherence
Performance Test Driven Development with Oracle Coherence
aragozin
 
Test in action – week 1
Test in action – week 1Test in action – week 1
Test in action – week 1
Yi-Huan Chan
 
Android dev 3
Android dev 3Android dev 3
Android dev 3
Aravindharamanan S
 
Web Services Automated Testing via SoapUI Tool
Web Services Automated Testing via SoapUI ToolWeb Services Automated Testing via SoapUI Tool
Web Services Automated Testing via SoapUI Tool
Sperasoft
 
Jdbc presentation
Jdbc presentationJdbc presentation
Jdbc presentation
nrjoshiee
 
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
Jen Wong
 
Test in action week 2
Test in action   week 2Test in action   week 2
Test in action week 2
Yi-Huan Chan
 
SCWCD : Thread safe servlets : CHAP : 8
SCWCD : Thread safe servlets : CHAP : 8SCWCD : Thread safe servlets : CHAP : 8
SCWCD : Thread safe servlets : CHAP : 8
Ben Abdallah Helmi
 
Tdd iPhone For Dummies
Tdd iPhone For DummiesTdd iPhone For Dummies
Tdd iPhone For Dummies
Giordano Scalzo
 
Unit testing with Spock Framework
Unit testing with Spock FrameworkUnit testing with Spock Framework
Unit testing with Spock Framework
Eugene Dvorkin
 
Unit Testing in SharePoint 2010
Unit Testing in SharePoint 2010Unit Testing in SharePoint 2010
Unit Testing in SharePoint 2010
Chris Weldon
 
API-Testing-SOAPUI-1.pptx
API-Testing-SOAPUI-1.pptxAPI-Testing-SOAPUI-1.pptx
API-Testing-SOAPUI-1.pptx
amarnathdeo
 
Ajax Under The Hood
Ajax Under The HoodAjax Under The Hood
Ajax Under The Hood
WO Community
 
Servlets
ServletsServlets
The ASP.NET Web API for Beginners
The ASP.NET Web API for BeginnersThe ASP.NET Web API for Beginners
The ASP.NET Web API for Beginners
Kevin Hazzard
 
Unit Testng with PHP Unit - A Step by Step Training
Unit Testng with PHP Unit - A Step by Step TrainingUnit Testng with PHP Unit - A Step by Step Training
Unit Testng with PHP Unit - A Step by Step Training
Ram Awadh Prasad, PMP
 
Developer testing 201: When to Mock and When to Integrate
Developer testing 201: When to Mock and When to IntegrateDeveloper testing 201: When to Mock and When to Integrate
Developer testing 201: When to Mock and When to Integrate
LB Denker
 

Similar to Enhanced Web Service Testing: A Better Mock Structure (20)

Enhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock StructureEnhanced Web Service Testing: A Better Mock Structure
Enhanced Web Service Testing: A Better Mock Structure
 
Developer testing 101: Become a Testing Fanatic
Developer testing 101: Become a Testing FanaticDeveloper testing 101: Become a Testing Fanatic
Developer testing 101: Become a Testing Fanatic
 
Apex Testing and Best Practices
Apex Testing and Best PracticesApex Testing and Best Practices
Apex Testing and Best Practices
 
Performance Test Driven Development with Oracle Coherence
Performance Test Driven Development with Oracle CoherencePerformance Test Driven Development with Oracle Coherence
Performance Test Driven Development with Oracle Coherence
 
Test in action – week 1
Test in action – week 1Test in action – week 1
Test in action – week 1
 
Android dev 3
Android dev 3Android dev 3
Android dev 3
 
Web Services Automated Testing via SoapUI Tool
Web Services Automated Testing via SoapUI ToolWeb Services Automated Testing via SoapUI Tool
Web Services Automated Testing via SoapUI Tool
 
Jdbc presentation
Jdbc presentationJdbc presentation
Jdbc presentation
 
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
More on Fitnesse and Continuous Integration (Silicon Valley code camp 2012)
 
Test in action week 2
Test in action   week 2Test in action   week 2
Test in action week 2
 
SCWCD : Thread safe servlets : CHAP : 8
SCWCD : Thread safe servlets : CHAP : 8SCWCD : Thread safe servlets : CHAP : 8
SCWCD : Thread safe servlets : CHAP : 8
 
Tdd iPhone For Dummies
Tdd iPhone For DummiesTdd iPhone For Dummies
Tdd iPhone For Dummies
 
Unit testing with Spock Framework
Unit testing with Spock FrameworkUnit testing with Spock Framework
Unit testing with Spock Framework
 
Unit Testing in SharePoint 2010
Unit Testing in SharePoint 2010Unit Testing in SharePoint 2010
Unit Testing in SharePoint 2010
 
API-Testing-SOAPUI-1.pptx
API-Testing-SOAPUI-1.pptxAPI-Testing-SOAPUI-1.pptx
API-Testing-SOAPUI-1.pptx
 
Ajax Under The Hood
Ajax Under The HoodAjax Under The Hood
Ajax Under The Hood
 
Servlets
ServletsServlets
Servlets
 
The ASP.NET Web API for Beginners
The ASP.NET Web API for BeginnersThe ASP.NET Web API for Beginners
The ASP.NET Web API for Beginners
 
Unit Testng with PHP Unit - A Step by Step Training
Unit Testng with PHP Unit - A Step by Step TrainingUnit Testng with PHP Unit - A Step by Step Training
Unit Testng with PHP Unit - A Step by Step Training
 
Developer testing 201: When to Mock and When to Integrate
Developer testing 201: When to Mock and When to IntegrateDeveloper testing 201: When to Mock and When to Integrate
Developer testing 201: When to Mock and When to Integrate
 

More from Salesforce Developers

Sample Gallery: Reference Code and Best Practices for Salesforce Developers
Sample Gallery: Reference Code and Best Practices for Salesforce DevelopersSample Gallery: Reference Code and Best Practices for Salesforce Developers
Sample Gallery: Reference Code and Best Practices for Salesforce Developers
Salesforce Developers
 
Maximizing Salesforce Lightning Experience and Lightning Component Performance
Maximizing Salesforce Lightning Experience and Lightning Component PerformanceMaximizing Salesforce Lightning Experience and Lightning Component Performance
Maximizing Salesforce Lightning Experience and Lightning Component Performance
Salesforce Developers
 
Local development with Open Source Base Components
Local development with Open Source Base ComponentsLocal development with Open Source Base Components
Local development with Open Source Base Components
Salesforce Developers
 
TrailheaDX India : Developer Highlights
TrailheaDX India : Developer HighlightsTrailheaDX India : Developer Highlights
TrailheaDX India : Developer Highlights
Salesforce Developers
 
Why developers shouldn’t miss TrailheaDX India
Why developers shouldn’t miss TrailheaDX IndiaWhy developers shouldn’t miss TrailheaDX India
Why developers shouldn’t miss TrailheaDX India
Salesforce Developers
 
CodeLive: Build Lightning Web Components faster with Local Development
CodeLive: Build Lightning Web Components faster with Local DevelopmentCodeLive: Build Lightning Web Components faster with Local Development
CodeLive: Build Lightning Web Components faster with Local Development
Salesforce Developers
 
CodeLive: Converting Aura Components to Lightning Web Components
CodeLive: Converting Aura Components to Lightning Web ComponentsCodeLive: Converting Aura Components to Lightning Web Components
CodeLive: Converting Aura Components to Lightning Web Components
Salesforce Developers
 
Enterprise-grade UI with open source Lightning Web Components
Enterprise-grade UI with open source Lightning Web ComponentsEnterprise-grade UI with open source Lightning Web Components
Enterprise-grade UI with open source Lightning Web Components
Salesforce Developers
 
TrailheaDX and Summer '19: Developer Highlights
TrailheaDX and Summer '19: Developer HighlightsTrailheaDX and Summer '19: Developer Highlights
TrailheaDX and Summer '19: Developer Highlights
Salesforce Developers
 
Live coding with LWC
Live coding with LWCLive coding with LWC
Live coding with LWC
Salesforce Developers
 
Lightning web components - Episode 4 : Security and Testing
Lightning web components  - Episode 4 : Security and TestingLightning web components  - Episode 4 : Security and Testing
Lightning web components - Episode 4 : Security and Testing
Salesforce Developers
 
LWC Episode 3- Component Communication and Aura Interoperability
LWC Episode 3- Component Communication and Aura InteroperabilityLWC Episode 3- Component Communication and Aura Interoperability
LWC Episode 3- Component Communication and Aura Interoperability
Salesforce Developers
 
Lightning web components episode 2- work with salesforce data
Lightning web components   episode 2- work with salesforce dataLightning web components   episode 2- work with salesforce data
Lightning web components episode 2- work with salesforce data
Salesforce Developers
 
Lightning web components - Episode 1 - An Introduction
Lightning web components - Episode 1 - An IntroductionLightning web components - Episode 1 - An Introduction
Lightning web components - Episode 1 - An Introduction
Salesforce Developers
 
Migrating CPQ to Advanced Calculator and JSQCP
Migrating CPQ to Advanced Calculator and JSQCPMigrating CPQ to Advanced Calculator and JSQCP
Migrating CPQ to Advanced Calculator and JSQCP
Salesforce Developers
 
Scale with Large Data Volumes and Big Objects in Salesforce
Scale with Large Data Volumes and Big Objects in SalesforceScale with Large Data Volumes and Big Objects in Salesforce
Scale with Large Data Volumes and Big Objects in Salesforce
Salesforce Developers
 
Replicate Salesforce Data in Real Time with Change Data Capture
Replicate Salesforce Data in Real Time with Change Data CaptureReplicate Salesforce Data in Real Time with Change Data Capture
Replicate Salesforce Data in Real Time with Change Data Capture
Salesforce Developers
 
Modern Development with Salesforce DX
Modern Development with Salesforce DXModern Development with Salesforce DX
Modern Development with Salesforce DX
Salesforce Developers
 
Get Into Lightning Flow Development
Get Into Lightning Flow DevelopmentGet Into Lightning Flow Development
Get Into Lightning Flow Development
Salesforce Developers
 
Integrate CMS Content Into Lightning Communities with CMS Connect
Integrate CMS Content Into Lightning Communities with CMS ConnectIntegrate CMS Content Into Lightning Communities with CMS Connect
Integrate CMS Content Into Lightning Communities with CMS Connect
Salesforce Developers
 

More from Salesforce Developers (20)

Sample Gallery: Reference Code and Best Practices for Salesforce Developers
Sample Gallery: Reference Code and Best Practices for Salesforce DevelopersSample Gallery: Reference Code and Best Practices for Salesforce Developers
Sample Gallery: Reference Code and Best Practices for Salesforce Developers
 
Maximizing Salesforce Lightning Experience and Lightning Component Performance
Maximizing Salesforce Lightning Experience and Lightning Component PerformanceMaximizing Salesforce Lightning Experience and Lightning Component Performance
Maximizing Salesforce Lightning Experience and Lightning Component Performance
 
Local development with Open Source Base Components
Local development with Open Source Base ComponentsLocal development with Open Source Base Components
Local development with Open Source Base Components
 
TrailheaDX India : Developer Highlights
TrailheaDX India : Developer HighlightsTrailheaDX India : Developer Highlights
TrailheaDX India : Developer Highlights
 
Why developers shouldn’t miss TrailheaDX India
Why developers shouldn’t miss TrailheaDX IndiaWhy developers shouldn’t miss TrailheaDX India
Why developers shouldn’t miss TrailheaDX India
 
CodeLive: Build Lightning Web Components faster with Local Development
CodeLive: Build Lightning Web Components faster with Local DevelopmentCodeLive: Build Lightning Web Components faster with Local Development
CodeLive: Build Lightning Web Components faster with Local Development
 
CodeLive: Converting Aura Components to Lightning Web Components
CodeLive: Converting Aura Components to Lightning Web ComponentsCodeLive: Converting Aura Components to Lightning Web Components
CodeLive: Converting Aura Components to Lightning Web Components
 
Enterprise-grade UI with open source Lightning Web Components
Enterprise-grade UI with open source Lightning Web ComponentsEnterprise-grade UI with open source Lightning Web Components
Enterprise-grade UI with open source Lightning Web Components
 
TrailheaDX and Summer '19: Developer Highlights
TrailheaDX and Summer '19: Developer HighlightsTrailheaDX and Summer '19: Developer Highlights
TrailheaDX and Summer '19: Developer Highlights
 
Live coding with LWC
Live coding with LWCLive coding with LWC
Live coding with LWC
 
Lightning web components - Episode 4 : Security and Testing
Lightning web components  - Episode 4 : Security and TestingLightning web components  - Episode 4 : Security and Testing
Lightning web components - Episode 4 : Security and Testing
 
LWC Episode 3- Component Communication and Aura Interoperability
LWC Episode 3- Component Communication and Aura InteroperabilityLWC Episode 3- Component Communication and Aura Interoperability
LWC Episode 3- Component Communication and Aura Interoperability
 
Lightning web components episode 2- work with salesforce data
Lightning web components   episode 2- work with salesforce dataLightning web components   episode 2- work with salesforce data
Lightning web components episode 2- work with salesforce data
 
Lightning web components - Episode 1 - An Introduction
Lightning web components - Episode 1 - An IntroductionLightning web components - Episode 1 - An Introduction
Lightning web components - Episode 1 - An Introduction
 
Migrating CPQ to Advanced Calculator and JSQCP
Migrating CPQ to Advanced Calculator and JSQCPMigrating CPQ to Advanced Calculator and JSQCP
Migrating CPQ to Advanced Calculator and JSQCP
 
Scale with Large Data Volumes and Big Objects in Salesforce
Scale with Large Data Volumes and Big Objects in SalesforceScale with Large Data Volumes and Big Objects in Salesforce
Scale with Large Data Volumes and Big Objects in Salesforce
 
Replicate Salesforce Data in Real Time with Change Data Capture
Replicate Salesforce Data in Real Time with Change Data CaptureReplicate Salesforce Data in Real Time with Change Data Capture
Replicate Salesforce Data in Real Time with Change Data Capture
 
Modern Development with Salesforce DX
Modern Development with Salesforce DXModern Development with Salesforce DX
Modern Development with Salesforce DX
 
Get Into Lightning Flow Development
Get Into Lightning Flow DevelopmentGet Into Lightning Flow Development
Get Into Lightning Flow Development
 
Integrate CMS Content Into Lightning Communities with CMS Connect
Integrate CMS Content Into Lightning Communities with CMS ConnectIntegrate CMS Content Into Lightning Communities with CMS Connect
Integrate CMS Content Into Lightning Communities with CMS Connect
 

Recently uploaded

Taking AI to the Next Level in Manufacturing.pdf
Taking AI to the Next Level in Manufacturing.pdfTaking AI to the Next Level in Manufacturing.pdf
Taking AI to the Next Level in Manufacturing.pdf
ssuserfac0301
 
"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
Fwdays
 
Dandelion Hashtable: beyond billion requests per second on a commodity server
Dandelion Hashtable: beyond billion requests per second on a commodity serverDandelion Hashtable: beyond billion requests per second on a commodity server
Dandelion Hashtable: beyond billion requests per second on a commodity server
Antonios Katsarakis
 
Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |
AstuteBusiness
 
Y-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PPY-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PP
c5vrf27qcz
 
Skybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoptionSkybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoption
Tatiana Kojar
 
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
Jason Yip
 
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAUHCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
panagenda
 
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing InstancesEnergy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
Alpen-Adria-Universität
 
Generating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and MilvusGenerating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and Milvus
Zilliz
 
Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024
Jason Packer
 
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectorsConnector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
DianaGray10
 
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
Edge AI and Vision Alliance
 
"Choosing proper type of scaling", Olena Syrota
"Choosing proper type of scaling", Olena Syrota"Choosing proper type of scaling", Olena Syrota
"Choosing proper type of scaling", Olena Syrota
Fwdays
 
Introduction of Cybersecurity with OSS at Code Europe 2024
Introduction of Cybersecurity with OSS  at Code Europe 2024Introduction of Cybersecurity with OSS  at Code Europe 2024
Introduction of Cybersecurity with OSS at Code Europe 2024
Hiroshi SHIBATA
 
JavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green MasterplanJavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green Masterplan
Miro Wengner
 
Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
Pitangent Analytics & Technology Solutions Pvt. Ltd
 
Principle of conventional tomography-Bibash Shahi ppt..pptx
Principle of conventional tomography-Bibash Shahi ppt..pptxPrinciple of conventional tomography-Bibash Shahi ppt..pptx
Principle of conventional tomography-Bibash Shahi ppt..pptx
BibashShahi
 
AppSec PNW: Android and iOS Application Security with MobSF
AppSec PNW: Android and iOS Application Security with MobSFAppSec PNW: Android and iOS Application Security with MobSF
AppSec PNW: Android and iOS Application Security with MobSF
Ajin Abraham
 

Recently uploaded (20)

Taking AI to the Next Level in Manufacturing.pdf
Taking AI to the Next Level in Manufacturing.pdfTaking AI to the Next Level in Manufacturing.pdf
Taking AI to the Next Level in Manufacturing.pdf
 
"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk"Frontline Battles with DDoS: Best practices and Lessons Learned",  Igor Ivaniuk
"Frontline Battles with DDoS: Best practices and Lessons Learned", Igor Ivaniuk
 
Dandelion Hashtable: beyond billion requests per second on a commodity server
Dandelion Hashtable: beyond billion requests per second on a commodity serverDandelion Hashtable: beyond billion requests per second on a commodity server
Dandelion Hashtable: beyond billion requests per second on a commodity server
 
Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |Astute Business Solutions | Oracle Cloud Partner |
Astute Business Solutions | Oracle Cloud Partner |
 
Y-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PPY-Combinator seed pitch deck template PP
Y-Combinator seed pitch deck template PP
 
Skybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoptionSkybuffer SAM4U tool for SAP license adoption
Skybuffer SAM4U tool for SAP license adoption
 
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
[OReilly Superstream] Occupy the Space: A grassroots guide to engineering (an...
 
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAUHCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
HCL Notes und Domino Lizenzkostenreduzierung in der Welt von DLAU
 
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing InstancesEnergy Efficient Video Encoding for Cloud and Edge Computing Instances
Energy Efficient Video Encoding for Cloud and Edge Computing Instances
 
Generating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and MilvusGenerating privacy-protected synthetic data using Secludy and Milvus
Generating privacy-protected synthetic data using Secludy and Milvus
 
Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024Columbus Data & Analytics Wednesdays - June 2024
Columbus Data & Analytics Wednesdays - June 2024
 
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectorsConnector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
Connector Corner: Seamlessly power UiPath Apps, GenAI with prebuilt connectors
 
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
“Temporal Event Neural Networks: A More Efficient Alternative to the Transfor...
 
"Choosing proper type of scaling", Olena Syrota
"Choosing proper type of scaling", Olena Syrota"Choosing proper type of scaling", Olena Syrota
"Choosing proper type of scaling", Olena Syrota
 
Artificial Intelligence and Electronic Warfare
Artificial Intelligence and Electronic WarfareArtificial Intelligence and Electronic Warfare
Artificial Intelligence and Electronic Warfare
 
Introduction of Cybersecurity with OSS at Code Europe 2024
Introduction of Cybersecurity with OSS  at Code Europe 2024Introduction of Cybersecurity with OSS  at Code Europe 2024
Introduction of Cybersecurity with OSS at Code Europe 2024
 
JavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green MasterplanJavaLand 2024: Application Development Green Masterplan
JavaLand 2024: Application Development Green Masterplan
 
Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
Crafting Excellence: A Comprehensive Guide to iOS Mobile App Development Serv...
 
Principle of conventional tomography-Bibash Shahi ppt..pptx
Principle of conventional tomography-Bibash Shahi ppt..pptxPrinciple of conventional tomography-Bibash Shahi ppt..pptx
Principle of conventional tomography-Bibash Shahi ppt..pptx
 
AppSec PNW: Android and iOS Application Security with MobSF
AppSec PNW: Android and iOS Application Security with MobSFAppSec PNW: Android and iOS Application Security with MobSF
AppSec PNW: Android and iOS Application Security with MobSF
 

Enhanced Web Service Testing: A Better Mock Structure

  • 1. Enhanced Web Service Testing ​ Kirk Steffke ​ AppExchange Practice Lead ​ kirk@crmscience.com ​ @kirkevonphilly ​  A Better Mock Structure
  • 2. •  Test Coverage Overview •  Review of Native Testing Methods •  WebServiceMock and HttpCalloutMock Interfaces •  StaticResourceCalloutMock •  MultiStaticResourceCalloutMock •  Sample Scenario •  Better Mock Structure •  Setup •  Review Agenda ​ During this session
  • 3. Test Coverage Overview The who, what, when, where, and why’s of creating coverage
  • 4. •  Code we write… •  …about the code we just wrote •  Test classes •  Independent of code being tested •  One or more test methods •  @isTest annotation Apex Test Coverage ​ “What” with a Hint of “How”
  • 5. Apex Test Coverage ​ A Bit More of “How” Grandma’s Famous Recipe 1.  Write code to do something 2.  Create test class 3.  Mark with @isTest 4.  Create test method 5.  Create test data 6.  Invoke code being tested 7.  Assert (+ or -)
  • 6. •  Code we write… •  …about the code we just wrote •  Test classes •  Independent of code being tested •  One or more test method Apex Test Coverage Now More “What”
  • 7. •  You, me, everyone •  Required •  75% •  Ongoing Development •  Help catch regressions •  Positive and negative assertions Apex Test Coverage ​ “Who-ot” and “Why”
  • 8. •  As you’re developing •  Moving code from sandbox to production •  Creating packages Apex Test Coverage ​ When
  • 9. Native Testing Strategies The Tools that are Already in your Toolbox
  • 10. •  Class w/ single method that makes a callout Sample Scenario: Single Callout ​ Class Needing Coverage
  • 11. Sample Scenario: Single Callout ​ Class Needing Coverage ​ Gist: https://gist.github.com/KirkSteffke/2ca4357c7e84eece9073
  • 12. •  Method making callout needs coverage •  Don’t want test methods to actually make callout! •  Responses to be used for positive/negative tests Sample Scenario: Testing Objective ​ What We Need to Test
  • 13. •  Defined within test class •  Returns single callout response •  WebServiceMock for WSDL based SOAP callouts •  HttpCalloutMock for testing Http callouts •  Defined by content of text file in Static Resource •  Returns response for a single endpoint •  Similar to StaticResourceCalloutMock •  Static Resource contains response for multiple endpoints WebServiceMock and HttpCalloutMock Interfaces StaticResourceCalloutMock MultiStaticResourceCalloutMo ck Documentation: bit.ly/df15mock3Documentation: bit.ly/df15mock1 Documentation: bit.ly/df15mock2 Options for Testing HTTP Callouts ​ Out-of-the-box Tools
  • 14. •  Defined within test class •  Returns single callout response •  WebServiceMock for WSDL based SOAP callouts •  HttpCalloutMock for testing Http callouts •  Defined by content of text file in Static Resource •  Returns response for a single endpoint •  Similar to StaticResourceCalloutMock •  Static Resource contains response for multiple endpoints WebServiceMock and HttpCalloutMock Interfaces StaticResourceCalloutMock MultiStaticResourceCalloutMo ck Documentation: bit.ly/df15mock3Documentation: bit.ly/df15mock1 Documentation: bit.ly/df15mock2 Options for Testing HTTP Callouts ​ Out-of-the-box Tools
  • 15. •  Not “the” test, but is @test •  Called by test class methods •  Returns “mock” responses •  Sets up header, body, and status code HttpCalloutMock Interface ​ Part 1: Mock Responder Class
  • 16. HttpCalloutMock Interface ​ Part 1: Mock Responder Class ​ Gist: https://gist.github.com/KirkSteffke/0d1f22c77b6d3a2f5599
  • 17. •  Test class for class making callout (part 1) •  Utilizes Mock Responder Class (part 2) •  Respond from callout comes from responder class (part 2) HttpCalloutMock Interface ​ Part 2: Test Coverage
  • 20. •  Defined within test class •  Returns single callout response •  WebServiceMock for WSDL based SOAP callouts •  HttpCalloutMock for testing Http callouts •  Defined by content of text file in Static Resource •  Returns response for a single endpoint •  Similar to StaticResourceCalloutMock •  Static Resource contains response for multiple endpoints WebServiceMock and HttpCalloutMock Interfaces StaticResourceCalloutMock MultiStaticResourceCalloutMo ck Documentation: bit.ly/df15mock3Documentation: bit.ly/df15mock1 Documentation: bit.ly/df15mock2 Options for Testing HTTP Callouts ​ Out-of-the-box Tools
  • 21. StaticResourceCalloutMock Part 1: The static resource •  Only contains JSON text •  Can’t be a zipped static resource w/ multiple files •  mock.setStaticResource(‘Name of Zip’,’File in Zip’)
  • 22. StaticResourceCalloutMock ​ Part 2: Test coverage •  Slightly different from last example •  No separate class; defined within coverage •  StaticResourceCalloutMock object instead of class with HttpCalloutMock interface
  • 24. •  Defined within test class •  Returns single callout response •  WebServiceMock for WSDL based SOAP callouts •  HttpCalloutMock for testing Http callouts •  Defined by content of text file in Static Resource •  Returns response for a single endpoint •  Similar to StaticResourceCalloutMock •  Static Resource contains response for multiple endpoints WebServiceMock and HttpCalloutMock Interfaces StaticResourceCalloutMock MultiStaticResourceCalloutMo ck Documentation: bit.ly/df15mock3Documentation: bit.ly/df15mock1 Documentation: bit.ly/df15mock2 Options for Testing HTTP Callouts ​ Out-of-the-box Tools
  • 25. •  Two methods making callouts •  One method using both MultiStaticResourceCalloutMock Part 1: Modified Scenario
  • 26. •  Similar to StaticResourceCalloutMock •  Define multiple endpoints •  Each has own Static Resource •  Still no Zip file MultiStaticResourceCalloutMock Part 2: Test Coverage Static Resource: Example3_bar1 Static Resource: Example3_bar2
  • 27. MultiStaticResourceCalloutMock Part 2: Test Coverage 1.  New MultiStaticResourceCalloutMock() 2.  Set endpoint based resources 3.  Set mock 4.  Invoke callouts 5.  Perform assertions
  • 28. Complex Scenario A hypothetical, but real-world model to help you digest
  • 29. •  Batch job •  Import of Contacts from remote system •  Remote system has an API •  Two endpoints •  /api/ContactCount •  /api/Contacts Remote Import via Batch Overview
  • 30. •  /api/ContactCount •  Returns # of Contact records to be imported •  Result can change during span of batch execution •  /api/Contacts •  Returns x number of contacts •  Paginated •  Page=1 – returns 1st 200 records •  Page=2 – returns 2nd 200 records •  …and so on Remote Import via Batch Meet the Endpoints
  • 31. 1.  Batch is called 2.  Start() method 3.  Each execute() iteration performs 2 callouts 4.  1st checks total # of records available 5.  2nd imports records 6.  End of execute determines if more records? 7.  Execute may run for many iterations 8.  If no more records or limits, finish() 9.  Restart cycle 10.  End Remote Import via Batch Batch Flow
  • 32. Better Mock Structure Using our tools to make better tools
  • 33. Limitations Working with Our Tools •  HttpCalloutMock Interface and StaticResourceMock •  Can only handle one endpoint •  Single response •  Single setup prior to invoking actual callouts •  MultiStaticResourceCalloutMock •  Handle multiple endpoints •  Single response for each •  Single setup prior to invoking actual callouts
  • 34. Problems Continued… •  Challenge •  Use one or more standard tool •  Extend the usage •  Create queue of expected responses per endpoint •  Consider re-usability
  • 35. •  MakeCallouts Method •  Loops 10x •  Builds string of results •  ContactCount Method •  Makes Callout •  Contacts Method •  Makes callout •  Page Parameter Building the Problem Example4_CalloutClass.apxc public class Example4_CalloutClass { // Method to simulate all the callouts in our batch flow public static string MakeCallouts() { // Property to return string results = ''; // Let's call each resource 10x and... for (integer i = 0; i < 10; i++) { // ...add to results string this Count's response's body results += 'Count (' + i + '): ' + CalloutContactCount().getBody() + 'rn'; // ...add to results string this Contact response's body results += 'Contacts (' + i + '): ' + CalloutContacts(i).getBody() + 'rn'; } // Return concatenated string of results return results;
  • 36. •  ResponseMap •  By method •  By endpoint •  List of responses •  Respond •  Verify request •  Prepare response •  Discard •  Resp Class Building the Solution TestCalloutResponseGenerator.apxc @isTest global class TestCalloutResponseGenerator implements HttpCalloutMock { // Property and getter (semi init'd) to pair method --> endpoint --> list of responses private static map<string, map<string, list<resp>>> ResponseMap; public static map<string, map<string, list<resp>>> getResponseMap() { if (ResponseMap == null) { ResponseMap = new map<string, map<string, list<resp>>>(); // For each setMethod() method type, pre-pop. w/ empty map for (string method :new list<string>{'GET','PUT','POST','DELETE','HEAD','TRACE'}) ResponseMap.put(method, new map<string, list<resp>>()); } return ResponseMap; } // Required respond() method for HttpCalloutMock public HttpResponse Respond(HttpRequest req) {
  • 37. •  Body (JSON) •  Status (success) •  StatusCode •  Discard Building the Solution TestCalloutResponseGenerator.Resp // Class to hold details of response from within test methods public class Resp { public string body { get; set; } public string status { get; set; } public integer statusCode { get; set; } public boolean discard { get; set; } public Resp(string body, string status, integer statusCode, boolean discard) { this.body = body; this.status = status; this.statusCode = statusCode; this.discard = discard; } }
  • 38. •  ResponseMap •  By method •  By endpoint •  List of responses Building the Solution TestCalloutResponseGenerator.getResponseMap() // Property to pair method --> endpoint --> list of responses private static map<string, map<string, list<resp>>> ResponseMap; // Getter to return or prepare a semi init'd response map public static map<string, map<string, list<resp>>> getResponseMap() { if (ResponseMap == null) { ResponseMap = new map<string, map<string, list<resp>>>(); // For each setMethod() method type, pre-pop. w/ empty map for (string method :new list<string>{'GET','PUT','POST','DELETE','HEAD','TRACE'}) ResponseMap.put(method, new map<string, list<resp>>()); } return ResponseMap; }
  • 39. •  Respond •  Verify request •  Prepare response •  Discard Building the Solution TestCalloutResponseGenerator.Respond(HttpRequest req) // Required respond() method for HttpCalloutMock public HttpResponse Respond(HttpRequest req) { // Property for returned response HttpResponse res = new HttpResponse(); // Ensure HttpRequest is valid if (req != null && !string.isBlank(req.getMethod()) && !string.isBlank(req.getEndPoint())) { // Verify the Response map contains the req's method and endpoint if (getResponseMap().containsKey(req.getMethod()) && getResponseMap().get(req.getMethod()).containsKey(req.getEndpoint()) ) { // Instantiate a list of the method/endpoint's response bodies list<resp> respList = getResponseMap().get(req.getMethod()).get(req.getEndpoint()); // If there's at least one, use it - otherwise, output an error if (!respList.isEmpty()) {
  • 40. •  Setup ResponseMap •  Shortcut Explanation •  Contacts •  ContactCount •  Discard •  Set mock •  Invoke Callout Testing the Solution Example4_TestCalloutClass.TestWithPattern() @isTest public class Example4_TestCalloutClass { public static testMethod void TestWithPattern() { /* The below is just a shortcut for the demo. Instead of this 10x (1 per page): TestCalloutResponseGenerator.getResponseMap().get('GET').put( '/api/Contacts?page=1', new list<TestCalloutResponseGenerator.Resp> { new TestCalloutResponseGenerator.Resp( '{"Contacts":"data...page 1'"}', 'success', 200, false ) } ); */ // Temporary collection to hold looped results (for demo, we don't care about actual data,
  • 41. Testing the Solution Example4_TestCalloutClass.TestWithPattern() // Temporary collection to hold looped results (for demo, we don't care about actual data, just proof of concept) map<string, list<TestCalloutResponseGenerator.Resp>> pagedResponses = new map<string, list<TestCalloutResponseGenerator.Resp>>(); // Create a dummy response for Contact callout for our "10" pages of contacts for (integer i = 0; i < 10; i++) { // Each loop = 1 page pagedResponses.put('/api/Contacts?page=' + i, new list<TestCalloutResponseGenerator.Resp>{ new TestCalloutResponseGenerator.Resp( '{"Contacts":"data...' + i + '"}', 'success', 200, true) }); } // Add all of the contact responses to the response map TestCalloutResponseGenerator.getResponseMap().put('GET', pagedResponses);
  • 42. •  Setup ResponseMap •  Shortcut Explanation •  Contacts •  ContactCount •  Discard •  Set mock •  Invoke Callout Testing the Solution Example4_TestCalloutClass.TestWithPattern() // Enable mock response Test.setMock(HttpCalloutMock.class, new TestCalloutResponseGenerator()); // Invoke the callout method string results = Example4_CalloutClass.MakeCallouts(); system.debug('Results: rnrn' + results);
  • 43. Testing the Solution TestCalloutClass 1.  Count or Contact callout 2.  # of loop iteration 3.  Count data 10, 12, 12, … 1.  Use 1st, discard 2.  Use 2nd, don’t discard 4.  Contact data increments 1.  Provided per page response