LET'S LEARN TOGETHER. THE BEAUTIFUL THING ABOUT LEARNING IS NOBODY CAN TAKE IT AWAY FROM YOU.

Spring '15 - New Feature Added - @testSetup

One of the very interesting feature added in Spring '15 is @testSetup. In this post I will try to explain with example more about the feature. 
Below is what you will get from release note about @testSetup.

Now let's check with example -

Below is the class/methods for which we need to write test methods - 
public class AccountHelper {
    public List<Account> getAllAccounts(){
        List<Account> allAccounts = [Select Id from Account];
        return allAccounts;
    }
    
    public Integer getEmployeeCountFrom(String accountNumber){
        Account fetchedAccount = [Select Id, NumberOfEmployees from Account where AccountNumber = :accountNumber LIMIT 1];
        return fetchedAccount.NumberOfEmployees;
    }
    
    public List<Case> getAllCases(Id accountId){
        return [select ID from Case where AccountId = :accountId];
    }
    
    public void updateEmployeeCountFor(String accountNumber, Integer newEmployeeCount){
        Account fetchedAccount = [Select Id, NumberOfEmployees from Account where AccountNumber = :accountNumber LIMIT 1];
        fetchedAccount.NumberOfEmployees = newEmployeeCount;
        update fetchedAccount;
    }
}

Previously we used to write test classes like below -
@isTest
public class AccountHelperTest {
    static testMethod void testGetAllAccounts(){
        List<Account> accounts = new List<Account>();
        for(Integer i=0;i < 100;i++){
            accounts.add(new Account(Name = 'Universal Container'));
        }
        insert accounts;
        
        Test.startTest();
        AccountHelper accountHelper = new AccountHelper();
        List<Account> allAccounts = accountHelper.getAllAccounts();
        Test.stopTest();
        
        System.assertEquals(100, allAccounts.size());
    }
    
    static testMethod void testGetEmployeeCountFrom(){
        Account anAccount = new Account();
        anAccount.Name = 'Universal Container';
        anAccount.AccountNumber = 'TEST';
        anAccount.NumberOfEmployees = 100;
        
        insert anAccount;
        
        Test.startTest();
        AccountHelper accountHelper = new AccountHelper();
        Integer numberOfEmployees = accountHelper.getEmployeeCountFrom('TEST');
        Test.stopTest();
        
        System.assertEquals(100, numberOfEmployees);
    }
    
    static testMethod void testGetAllCases(){
        //Create the account first
        Account anAccount = new Account();
        anAccount.Name = 'Universal Container';
        insert anAccount;
        
        //Create the cases now
        List<Case> cases = new List<Case>();
        for(Integer i=0;i < 10;i++){
            cases.add(new Case(
                Status = 'New',
                Priority = 'Medium',
                AccountId = anAccount.Id,
                Origin = 'Phone'
            ));
        }
        insert cases;
        
        Test.startTest();
        AccountHelper accountHelper = new AccountHelper();
        List<Case> allCases = accountHelper.getAllCases(anAccount.id);
        Test.stopTest();
        
        System.assertEquals(10, allCases.size());
    }
}

The disadvantages with this approach is that for every test method we need to write block of codes to setup data. Why not create test data for all the test methods in a test class once and use them everywhere. More organised, right? Exactly that is what we can do now with methods annotated with @testSetup. The method annotated with @testSetup will be responsible for setting up test data at the very beginning before executing the first test method. When all the test methods are executed successfully, the test data will be roll backed automatically. Another advantage with this approach is that if any test method modifies the test data, the modification will be roll backed after executing that particular test method. So the next test method will get the original test data being setup at the beginning.

Let's see how we can write test methods using new approach -
@isTest
public class ApexHelperTestAdvanced {
    @testSetup static void setup() {
        // Create common test accounts
        List<Account> accounts = new List<Account>();
        for(Integer i=0;i < 100;i++){
            accounts.add(new Account(Name = 'Universal Container'));
        }
        
        //Add few account details to one Account
        accounts[0].AccountNumber = 'TEST';
        accounts[0].NumberOfEmployees = 100;
        
        //Insert Account
        insert accounts;
        
        //Add Case Details
        List<Case> cases = new List<Case>();
        for(Integer i=0;i < 10;i++){
            cases.add(new Case(
                Status = 'New',
                Priority = 'Medium',
                AccountId = accounts[0].Id,
                Origin = 'Phone'
            ));
        }
        
        //Insert cases
        insert cases;        
    }
    
    static testMethod void testGetAllAccounts(){
        Test.startTest();
        AccountHelper accountHelper = new AccountHelper();
        List<Account> allAccounts = accountHelper.getAllAccounts();
        Test.stopTest();
        
        System.assertEquals(100, allAccounts.size());
    }
    
    static testMethod void testGetEmployeeCountFrom(){
        Test.startTest();
        AccountHelper accountHelper = new AccountHelper();
        Integer numberOfEmployees = accountHelper.getEmployeeCountFrom('TEST');
        Test.stopTest();
        
        System.assertEquals(100, numberOfEmployees);
    }
    
    static testMethod void testGetAllCases(){
        //Fetch the account ID
        Account fetchedAccount = [Select Id from Account where AccountNumber = 'Test'];
        
        Test.startTest();
        AccountHelper accountHelper = new AccountHelper();
        List<Case> allCases = accountHelper.getAllCases(fetchedAccount.id);
        Test.stopTest();
        
        System.assertEquals(10, allCases.size());
    }
    
    static testMethod void testUpdateEmployeeCountFor(){
        Test.startTest();
        AccountHelper accountHelper = new AccountHelper();
        accountHelper.updateEmployeeCountFor('TEST',200);
        Integer numberOfEmployees = accountHelper.getEmployeeCountFrom('TEST');
        Test.stopTest();
        
        System.assertEquals(200, numberOfEmployees);
    }
    
    static testMethod void testRollBackFunctionality(){
        Test.startTest();
        AccountHelper accountHelper = new AccountHelper();
        Integer numberOfEmployees = accountHelper.getEmployeeCountFrom('TEST');
        Test.stopTest();
        
        System.assertEquals(100, numberOfEmployees);
    }
}

Here as you can see we have a method named setup annotated with @testSetup and this method will setup all the test data. Now from the test methods we are not calling any method or doing something to setup data. It is being setup already by the method "setup" at the beginning. Great, Awesome. So we are moving towards TDD (Test Driven Development) approach

Another point to notice here is that the testMethod name testUpdateEmployeeCountFor is basically modifying the test data by making the number of employees to 200. Now in the next test method i.e. testRollBackFunctionality, we are checking whether the number of employees is again 100 (original values setup earlier). It indicates that any modification in test data by any test method will be rolled back at the end of the execution of that test method. 

Below are few points which we should keep in mind as - 

Try this new feature in your own Spring '15 Pre-release Org! 
Please provide your feedback. Thanks.

Share:

No comments:

Post a Comment

Never miss a post. Subscribe to get latest blog posts, right into your email box.

* indicates required

Labels

Salesforce (105) Apex (51) admin (28) visualforce (21) ADM (20) dev 501 (19) lightning (19) integration (18) learn salesforce (18) 501 (16) javascript (14) SOAP (13) tutorial (11) Certification. (10) Advanced Apex (9) Kitchener Developer Group (8) test class (8) Certification (7) Trigger (7) flow (7) security (7) unit testing (7) Advanced Admin (6) Lightning Experience (6) Sharing and Visibility (6) design pattern (6) developer (6) report (6) salesforce release (6) service cloud (6) trailhead (6) use case (6) Lightning Feature (5) New Features (5) SOQL (5) css (5) dashboard (5) debug (5) formula (5) mobile (5) solution management (5) JSON (4) Kitchener User Group (4) Lightning Web Component (4) New Feature (4) Sales Cloud (4) Salesforce DX (4) Tips (4) WebSphere (4) best practice (4) cast iron (4) component (4) deployment (4) event (4) github (4) html (4) map (4) polymer (4) profiles (4) release (4) responsive (4) tdd (4) ui (4) visual studio code (4) Architect (3) Live Chat (3) Online Event (3) Opportunity (3) Performance (3) Products (3) REST (3) Role (3) Salesforce Certification (3) Scratch Org (3) Spring 20 (3) Study Notes. (3) Summer15 (3) VS Code (3) Web Technology (3) Winter21 (3) automation tool (3) configuration (3) dynamic apex (3) license (3) mapbox (3) singleton (3) version controlling (3) AppExchange (2) Article (2) Asynchronous Apex (2) Asynchronous callout (2) Aura Framework (2) Bulkify (2) Community (2) Data Architecture and Management Certification (2) Devops (2) Distributed Version Controlling (2) ES6 (2) Eclipse (2) Einstein (2) Enhancement (2) Enterprise Territory Management (2) Financial Services Cloud (2) Force.com IDE (2) Governor Limit (2) Groups (2) IBM (2) Implicit Sharing (2) JourneyToCTA (2) Knowledge Management (2) LWC (2) Lightning Design System (2) Live Agent (2) Metadata (2) PD II (2) Price Book (2) Queueable (2) SFDX (2) SOSL (2) Sharing (2) Spring 15 (2) Summer17 (2) Territory (2) Virtual Event (2) ant (2) basic (2) chatter (2) code coverage (2) coding (2) communication (2) console (2) controller (2) documentation (2) dreamforce (2) git (2) jquery (2) logging (2) object (2) permission (2) process builder (2) salesforce1 (2) strategy (2) visual workflow (2) xml (2) Action Plan (1) Action Plan Template (1) Activity Timeline (1) Advanced Currency (1) Agent Productivity (1) Analytics (1) Apex Sharing (1) Arrow (1) Batch (1) Bots (1) Browser (1) Bulk data load (1) CTA (1) Calendar (1) Canon (1) Case Management (1) Celebration (1) Cheat Sheet (1) Classic (1) Compare (1) Confetti (1) Constructor (1) Contact Center (1) Continuation (1) Continuous Integration (1) Convert (1) Cookie (1) CumulusCI (1) Custom Metadata (1) Custom Object (1) Custom Permission (1) Customer (1) Data Model (1) DataGrid (1) DataTable (1) Dated Exchange Rate (1) Decorator Design Pattern (1) Dev Hub (1) Development (1) Diwali (1) EDA (1) ESLint (1) Education Cloud (1) Email (1) FSC (1) Function (1) Future (1) Global Gathering (1) Goals (1) Guest Access (1) Guest Profile (1) Guest User Sharing Rule (1) Guide (1) HEDA (1) Higher Education (1) Household (1) Husky (1) IDE (1) Ideas (1) Improvement (1) Invocable (1) KPIs (1) Large Data Volume (1) LastModifiedDate (1) Manage Currencies (1) Manual Sharing (1) Metrics (1) Multi Currency (1) New (1) OOPS (1) OWD (1) Omni-Channel (1) Optimize (1) Partner (1) Permission Set (1) Person Account (1) Photo (1) Pipeline (1) Platform Developer I (1) Platform Developer II (1) Presentation (1) Prettier (1) Product Schedule (1) Profile (1) Promise (1) Prototype (1) Public Site (1) Query Plan (1) QuickReference (1) Related records (1) Reports (1) Retrieve (1) Role Hierarchy (1) SAL (1) Salesfor (1) Salesforce Advisor Link (1) Salesforce Labs (1) Salesforce Optimizer (1) SalesforceDx (1) Schedule (1) Session (1) Sharing Rule (1) Sharing Sets (1) Site (1) Skills (1) Snap-ins (1) Spring 17 (1) Summer14 (1) Summer16 (1) Summer19 (1) Switch (1) SystemModStamp (1) Tile (1) Timeline (1) Unauthorized Access (1) User License (1) Users (1) Validation Rule (1) Web (1) Webservice (1) Winter'15 (1) Winter'17 (1) access (1) actionFunction (1) actionPoller (1) actionRegion (1) actionSupport (1) agile (1) app (1) approval process (1) aura (1) awesome (1) backup (1) bitbucket (1) book (1) campaign (1) change set (1) cli (1) code (1) csv (1) custom button (1) custom settings (1) customization (1) data loader (1) database (1) delegate Admin (1) describe (1) dom (1) duplicate (1) dynamic (1) dynamic form (1) email template (1) email-to-case (1) equals (1) error (1) field-level security (1) folder (1) ftp (1) generic (1) gift (1) global describe (1) hashcode (1) import wizard (1) jenkins (1) keynote (1) long running requests (1) monitoring (1) mysql (1) page layout (1) personal (1) power of one (1) record type (1) relationship (1) request (1) review (1) solution (1) sub-tab (1) survey (1) tab (1) username (1) workflow (1)

Popular Posts

Total Pageviews

Contact Me

Name

Email *

Message *