2

I'm looking to update some of the APEX code that I got this communities help back in December. Reason for the update - we've decided to limit the number of accounts by role. So I wrote two triggers - one for each role.

However, my test class (although it passes with 79% coverage) still won't deploy to production. So I'm hoping you guys can help me understand why.

These tests pass ( 'In progress', 'Hold Over') but "On Deck" since it's creating 200+ records returns a "Too many SOQL queries" error. So I'm hoping you can help me write a better test class. **It's worth noting that I'm still new to APEX

Anyways - Below is my Trigger

trigger LimitAcctNumberBDR on Account (before update, before insert) {
    Set<String> includeStatus = New Set<String>{'On Deck', 'In Progress', 'Hold Over'};  
    Id userId = userInfo.getUserId(); //Since we call it a lot cache it. Not sure if it makes a significant difference though 
    ID UserRoleId = userinfo.getUserRoleId();

    Map<String,Integer> cnt = New Map<String,Integer>(); //Store the counts
    Set<integer> UrId = New Set<integer>();//Store the id   

    for(String s : includeStatus) cnt.put(s,0); //Default Values
    //The NOT IN filter is so we do not include the trigger records in the count since we will be incrementing them below
    for(AggregateResult ar : [Select Account_Status__c, Count(Id) num From Account Where Account_Status__c In :includeStatus AND Owner.UserRoleId = '00Ej0000000yLBp' AND OwnerId = :userId  AND Id NOT IN :trigger.new Group By Account_Status__c LIMIT 200]){
        cnt.put(
            (String)ar.get('Account_Status__c'),
            (Integer)ar.get('num') 
        );
        system.debug('aggregate problem'+ ar);
        system.debug('string' + cnt);
    }

    for (Account a : trigger.new) {
        if(a.OwnerId != userId ) continue; //if Not OwnerId match then continue

        //Lets increment based on the status here 
        cnt.put(
            a.Account_Status__c,
            cnt.containsKey(a.Account_Status__c) ? (cnt.get(a.Account_Status__c) + 1) : 1
        );
        system.debug('increment status'+ cnt + a);

        //Now check sizes
        if (a.account_status__c == 'On Deck') {
            if (cnt.get('On Deck') > 100) {
                a.adderror('You are limited to only 100 On Deck Accounts');
            }
            system.debug('on deck size' + cnt.get('On Deck'));
        } else if (a.account_status__c == 'In Progress') {
            if (cnt.get('In Progress') > 200) {
                a.addError('You are limited to only 200 In Progress Accounts');
            }
            system.debug('in progress size'+ cnt.get('In Progress'));
        } else if (a.account_status__c == 'Hold Over') {
            if (cnt.get('Hold Over') > 100) {
                a.adderror('You are limited to only 100 Hold Over Accounts');
            }
        }
        system.debug('Hold Over size'+ cnt.get('Hold Over'));
    }
}

And this is my test class:

@istest
public class TestRunAs {
    private static testMethod Void testRunAs(){ 
        Profile p = [Select ID From Profile WHERE Name = 'BDR Standard User'];
        User u = new User(Alias = 'BDR', email = 'bdr@force.com',EmailEncodingKey='UTF-8', LastName='TestUser', LanguageLocaleKey='en_US', 
                      LocaleSidKey='en_US', ProfileId = p.Id, RoleId = '00Ej0000000yLBp',
                      TimeZoneSidKey='America/Los_Angeles', UserName='bdr@force.com');

        System.runAs(u) {
            // The following code runs as user 'u' 
            System.debug('Current User: ' + UserInfo.getUserName());
            System.debug('Current Profile: ' + UserInfo.getProfileId());
        }
    }

    static testMethod void OnDeck() {
        Try{
            FOR(Integer i = 1; i<=101; i++){
                Account acc = new Account();
                acc.name = 'SFDC' + i;
                acc.Account_Status__c = 'On Deck';
                acc.Type = 'None';
                insert acc;
                system.debug('On Deck' + Acc);
            }
        } catch( DmlException e) {           
        }
    }

    static testmethod void InProg() {
        Try{
            FOR(Integer i = 1; i<200; i++){
                Account onhold = new Account();
                onhold.name = 'SFDC' + i;
                onhold.Account_Status__c = 'In Progress';
                onhold.Type = 'None';
                insert onhold;  
                system.debug('In Progress'+ onhold);
            }
        } catch( DmlException f) {
        }
    }

    Static testmethod void HoldOver() {
        Try{
            FOR(Integer i = 1; i<=101; i++){
                Account HoldOver = new Account();
                HoldOver.name = 'SFDC' + i;
                HoldOver.Account_Status__c = 'Hold Over';
                HoldOver.type = 'None';
                insert HoldOver;
                    system.debug('Hold Over'+ HoldOver);
                }
        } catch( DmlException g) {
        }
    }
}
5

You problem is the insert in the loop.

There are potentially other issues as well but this is the immediate cause. You will need to ensure that your code can handle bulk inserts so review that trigger..

static testMethod void OnDeck() {
    Account[] accList = New Account[]{}; //List to accounts to insert

    FOR(Integer i = 1; i<=151; i++){
        Account acc = new Account();
        acc.name = 'SFDC' + i;
        acc.Account_Status__c = 'On Deck';
        acc.Type = 'None';
        accList.add(acc); //Add to the list to insert
        system.debug('On Deck' + Acc);
    }

    insert accList; //Insert all accounts at once outside of the loop
}

And never wrap your test code in a try catch unless you are testing an error.

You will need to modify the InProg using the same technique as well

  • Ah, I didn't see the new answer notification when I was writing mine up. – John Towers Mar 7 '17 at 17:15
  • @eric And John! - THANKS! it should be noted that I am trying to catch an error that is thrown when you try to go over the number of accounts. So if you go over 100 then I want to catch the error. Thats why the try/catch. I'll also take another look at my trigger to see if I can clean it up a bit – B-Roge Mar 7 '17 at 17:31
  • 1
    @B-Roge - Ok, but you had nothing in your catch to validate the correct error was caught so really your test would pass if a different fatal error was encountered. – Eric Mar 7 '17 at 17:39
1

You're inserting your test account records one at a time instead of doing them all at once:

    FOR(Integer i = 1; i<=42; i++){
        Account HoldOver = new Account();
        HoldOver.name = 'SFDC' + i;
        HoldOver.Account_Status__c = 'Hold Over';
        HoldOver.type = 'None';
        insert HoldOver;
        system.debug('Hold Over'+ HoldOver);
}

Try changing your inserts to something like:

List<Account> TestAccounts = new List<Account>();
        FOR(Integer i = 1; i<=42; i++){
            Account HoldOver = new Account();
            HoldOver.name = 'SFDC' + i;
            HoldOver.Account_Status__c = 'Hold Over';
            HoldOver.type = 'None';
            TestAccounts.add(HoldOver);
            system.debug('Hold Over'+ HoldOver);
    }
insert TestAccounts;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.