+ Start a Discussion
Ryan ReeseRyan Reese 

Test Class Code?

Newb apex - how do I build test class for the following trigger and someone told me not to hardcode the chatter group id how should I reference it in the code?

trigger OppWonChatter on Opportunity (after insert, after update) {

String status;
String OppAccName;
String OppOwnerName;
String OppName;   
FeedItem post = new FeedItem();
    
    for(Opportunity o : Trigger.new) {
        if(o.OwnerId == '00560000001MxXV') { //It will not post record for for this user to group. changed last letter to cap v so i can test
            return;
        }
        else {
            if(Trigger.isInsert ) {
                if( o.IsWon == true ) { //This will be executed on new record insertion
                    for (Opportunity oppty : [SELECT Account.Name, Owner.Name, Name FROM Opportunity WHERE Id =:o.Id] ) {
                        OppAccName = oppty.Account.Name;
                     OppName = oppty.Name;
                    
                        
                        OppOwnerName = oppty.Owner.Name;
                    }   
                    
                    status = OppOwnerName + ' just won ' + OppName + '!';

                                                            
                    post.ParentId = '0F9m00000008ZTM';
                    post.Title = o.Name;   
                    post.Body = status;
                    
                    insert post;
                }
            }    
            else {
                if ( Trigger.isUpdate ) {
                    if( o.IsWon == true ) { //This will be executed on update to existing record
                        for (Opportunity oppty : [SELECT Account.Name, Owner.Name, Name FROM Opportunity WHERE Id =:o.Id] ) {
                            OppName = oppty.Name;
                            OppAccName = oppty.Account.Name;  
                            OppOwnerName = oppty.Owner.Name;
                        }        
                        status = OppOwnerName + ' just won ' + OppName + '!';
                                               
                        post.ParentId = '0F9m00000008ZTM';
                        post.Title = o.Name;
                        post.Body = status;
             
Balaji Chowdary GarapatiBalaji Chowdary Garapati
@Ryan Reese:

 You can use custom settings to store the ids, and refer them in your code, which gives you the flexibility to change it whenever needed.

For eg., create a custom setting named SFDC Ids which has api name SFDC_IDS__C and a field called value with api name value__c for that setting.

Create a record in custom setting say Name="your chatter group name" and value="id of the chatter group".

you can get the value of the id in the code like this:

SFDC_IDS__C.getInstance('your chatter group name').value__c // This will even save a query for you.

To access/create custom settings go to setup>Develop>custom settings
Ryan ReeseRyan Reese
Ok, I will try that. Would you be able to assist on the test class?
Balaji Chowdary GarapatiBalaji Chowdary Garapati

I can guide you:

First you need to prepare test data to test it!

@isTest
public class OppWonChatter_isTest{
    
public static testMethod void test_ChatterPostOnOpp(){


//Create custom setting data


SFDC_IDS__C testDataForExemptUser=new SFDC_IDS__C(Name='Name of Exempt User',Value__c=Userinfo.getUserId());

insert testDataForExemptUser;

SFDC_IDS__C testDataForIdToPostChatter=new SFDC_IDS__C(Name='Name of Exempt User',Value__c=Userinfo.getUserId());

insert testDataForIdToPostChatter;


//Create test data for account
Account testAccount=new Account(Name='sample Name');

insert testAccount;

//Create testUser

Profile systemAdminProfile = [SELECT Id FROM Profile WHERE Name='System Administrator'];
User testUser = new User(Alias = 'standt', Email='standarduser@testorg.com', EmailEncodingKey='UTF-8', LastName='Testing', LanguageLocaleKey='en_US', LocaleSidKey='en_US', ProfileId = systemAdminProfile.Id, TimeZoneSidKey='America/Los_Angeles', UserName='testUser565558454@OppWonChatter_isTest.com');

// create test data for Opportunity

opportunity testOpportunity=new Opportunity(Name='Sample name',AccountId=testAccount.id,IsWon=True);

//Assuming the owner will be you, the post code should cover, now change
insert testOpportunity;

testOpportunity.OwnerId=testUser.id;

update testOpportunity;
//Now the update on oppotunity will be fired by covering the last part of code



system.runAs(testUser){
    
opportunity testOpportunityByTestUser=new Opportunity(Name='Sample name',AccountId=testAccount.id,IsWon=True);

insert testOpportunityByTestUser;

update testOpportunityByTestUser;
}



}

}



And the tigger needs to be modified(suggestions):

* It is not bulkified - written a DML statement in a for loop. Try to capture everything into a list and do a DML on list after the loop closes
* you are doing a query inside a for loop, instead you can collect the opportunity ids all at once and query in bulk which saves your query.
in the above case you can get all the ids all at once using trigger.newMap.keyset(); then query all the opportunities with those ids and parse through them.
*Lot of repetitive lines of code, in case of insert or update there are few statements which can be clubed together so that you could save some lines of code as well as it looks pretty.


Note:I wrote the test class assuming you already used custom settings, if not you doesnt need to insert any custom setting in test class. instead you would need to query for the user with those hard coded ids which needs (SeeAllData=True) annotation.** Not suggestable, so use custom settings :)


Hope this will help you writing test class

Thanks,
balaji
Ryan ReeseRyan Reese
I think I am totally lost with the apex class. Your code is losing me so I tried using this code but received only 71% approval with errors. Is there anyway to make a small fix on the code below to get it passed through so I can deploy.

Component Error - opportunityProductEntryTests.theTests(), Details: System.DmlException: Delete failed. First exception on row 0 with id 00k60000009NoHFAA0; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Please update the reason we lost this deal.: [] Class.opportunityProductEntryExtension.onSave: line 173, column 1 Class.opportunityProductEntryTests.theTests: line 47, column 1

Apex Test Failure - opportunityProductEntryTests theTests System.DmlException: Delete failed. First exception on row 0 with id 00k60000009NoHFAA0; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Please update the reason we lost this deal.: []
Stack Trace: Class.opportunityProductEntryExtension.onSave: line 173, column 1 Class.opportunityProductEntryTests.theTests: line 47, column 1


@istest  (SeeAllData=True) 
private class OppWonTestClass {        
      static testMethod Void validateMethod(){           
            Opportunity oppn = new Opportunity();        
   oppn.Name = 'Test code - Apex trigger oppn';          
 oppn.StageName= 'Closed Won'; // Put your Stage Name         
  oppn.CloseDate = System.Today();          
 oppn.Won_Reason__c = 'Pricing';       
    oppn.Lost_Reason__c = 'Pricing';          
    insert oppn;                                             }   }

 
Balaji Chowdary GarapatiBalaji Chowdary Garapati
@Ryan Reese:

Sorry if i confused you, i tried to explain you the best practices to fix the code you posted as it  is vulnarable to hit governor limit due to lack of bulkification concept usage.
opportunityProductEntryTests  is a test class which is failing as it hit a validation rule in your org which is asking to enter the Reason why the deal is lost! Its your orgs customized features so i assume any outsider help will be limited as we will have no idea what type of customizations your org went thru.

Note: Im not sure you if you are running multiple test classes because if there is any error with "OppWonTestClass " it says the error is with that particular class.


Thanks,
balaji
 
Ryan ReeseRyan Reese
I am only running the trigger and class as provided above. I am not sure why it is referring to the Lost Reason. If an opportunity wins - user must populute Won Reason (I included this field in the trigger with Pricing field value). If a user loses the opportunity (Closed Lost) - They must update the lost reason but if my test data what i believe to be test data in the class is for a won opportunity why is it giving me an error for the lost reason
Ryan ReeseRyan Reese
Here is the opportunityProductEntryTests class - this was something that i installed last week from a package online to create a shopping cart type feature for opportunities but we dont require products on opportunities. When creating an opportunity it must be looking to this class but shouldnt have anything to do with lost reason.


@istest private class opportunityProductEntryTests {     static testMethod void theTests(){                  // You really should create test data, but I'm going to query instead         // It's my best shot of avoiding a test failure in most orgs         // Once you've installed this package though, you might want to write your own tests         // or at least customize these ones to make them more applicable to your org                      OpportunityLineItem oli = [select Id, PricebookEntryId, PricebookEntry.Pricebook2Id, PricebookEntry.Name, PriceBookEntry.Product2Id, OpportunityId, Opportunity.AccountId from OpportunityLineItem limit 1];                                          ////////////////////////////////////////         //  test opportunityProductEntry         ////////////////////////////////////////                  // load the page                PageReference pageRef = Page.opportunityProductEntry;         pageRef.getParameters().put('Id',oli.OpportunityId);         Test.setCurrentPageReference(pageRef);                  // load the extension         opportunityProductEntryExtension oPEE = new opportunityProductEntryExtension(new ApexPages.StandardController(oli.Opportunity));                  // test 'getChosenCurrency' method         if(UserInfo.isMultiCurrencyOrganization())             System.assert(oPEE.getChosenCurrency()!='');         else             System.assertEquals(oPEE.getChosenCurrency(),'');         // we know that there is at least one line item, so we confirm         Integer startCount = oPEE.ShoppingCart.size();         system.assert(startCount>0);         //test search functionality without finding anything         oPEE.searchString = 'michaelforce is a hip cat';         oPEE.updateAvailableList();         system.assert(oPEE.AvailableProducts.size()==0);                  //test remove from shopping cart         oPEE.toUnselect = oli.PricebookEntryId;         oPEE.removeFromShoppingCart();         system.assert(oPEE.shoppingCart.size()==startCount-1);                  //test save and reload extension         oPEE.onSave();         oPEE = new opportunityProductEntryExtension(new ApexPages.StandardController(oli.Opportunity));         system.assert(oPEE.shoppingCart.size()==startCount-1);                  // test search again, this time we will find something         oPEE.searchString = oli.PricebookEntry.Name;         oPEE.updateAvailableList();         system.assert(oPEE.AvailableProducts.size()>0);                // test add to Shopping Cart function         oPEE.toSelect = oPEE.AvailableProducts[0].Id;         oPEE.addToShoppingCart();         system.assert(oPEE.shoppingCart.size()==startCount);                          // test save method - WITHOUT quanitities and amounts entered and confirm that error message is displayed         oPEE.onSave();         system.assert(ApexPages.getMessages().size()>0);                  // add required info and try save again         for(OpportunityLineItem o : oPEE.ShoppingCart){             o.quantity = 5;             o.unitprice = 300;         }         oPEE.onSave();                  // query line items to confirm that the save worked         opportunityLineItem[] oli2 = [select Id from opportunityLineItem where OpportunityId = :oli.OpportunityId];         system.assert(oli2.size()==startCount);                  // test on new Opp (no pricebook selected) to make sure redirect is happening         Opportunity newOpp = new Opportunity(Name='New Opp',stageName='Pipeline',Amount=10,closeDate=System.Today()+30,AccountId=oli.Opportunity.AccountId);         insert(newOpp);         oPEE = new opportunityProductEntryExtension(new ApexPages.StandardController(newOpp));         System.assert(oPEE.priceBookCheck()!=null);                  // final quick check of cancel button         System.assert(oPEE.onCancel()!=null);                           ////////////////////////////////////////         //  test redirect page         ////////////////////////////////////////                  // load the page         pageRef = Page.opportunityProductRedirect;         pageRef.getParameters().put('Id',oli2[0].Id);         Test.setCurrentPageReference(pageRef);         // load the extension and confirm that redirect function returns something         opportunityProductRedirectExtension oPRE = new opportunityProductRedirectExtension(new ApexPages.StandardController(oli2[0]));         System.assert(oPRE.redirect()!=null);           } }
 
Ryan ReeseRyan Reese
I removed the validation rule so that it can pass through the test
Balaji Chowdary GarapatiBalaji Chowdary Garapati

@Ryan Reese:

  It might be more dangerous as every time you need to turn it off while deployment (users will be still working). Instead cant the validation rule bypass/exempt system admin profile users, so that there wont be any issues with testclass installed from unmanaged packages??