I was wondering if someone would be able to help me create a test class for the following code as I am programmatically challenged :) any help would be greatly appreciated!!! Thanks in advance!!!

trigger RFS_OpportunityValidations on Opportunity(before update){

    Set<Id> oppsToBeChecked = new Set<Id>();
    Profile adminId = [SELECT Id from Profile where Name='System Administrator' LIMIT 1];

    for(Opportunity o : trigger.new){
        if(o.Probability >= 70 && UserInfo.getProfileId() != adminId.Id){
    // check their products in greater detail
    if(!oppsToBeChecked.isEmpty()) { // maybe we don't need to run the query at all?   
        for(OpportunityLineItem oli : [SELECT OpportunityId 
        FROM OpportunityLineItem 
        WHERE OpportunityId IN :oppsToBeChecked
            AND PriceBookEntry.Product2.RecordType.DeveloperName = 'Prospect_Product' 
            AND PriceBookEntry.Product2.Approved__c = false]){

            trigger.newMap.get(oli.OpportunityId).addError('Opportunities with => 70% must not include Prospect Products. Please replace these with real SAP Products to continue.');

Here is my test case so far but am getting the following error and can't go any further:

Pass/Fail: Fail

Error Message: System.DmlException: Insert failed. First exception on row 0; first error: DUPLICATE_VALUE, This price definition already exists in this price book: []

Stack Trace: Class.RFS_OpptValTriggerTest.myUnitTest: line 38, column 1

private class RFS_OpptValTriggerTest {

    static testMethod void myUnitTest() {       

//Data Prep
//Create Account, Opportunity, Product, etc.
        Account acct1 = new Account(name='test Account One1');
        insert acct1;
//Create Opportunity on Account
        Opportunity Oppty1 = new Opportunity(name='test Oppty One1');
        Oppty1.StageName = 'Selected';
        Oppty1.CloseDate = Date.today() + 30;
        insert Oppty1;         

// Create Products 
         Product2 testprod1 = new Product2 (name='test product one1');
         testprod1.productcode = 'test pd code1one';
         testprod1.Approved__c = false;
         testprod1.CanUseRevenueSchedule = True;
         insert testprod1;
         Product2 testprod2 = new Product2 (name='test product two2');
         testprod2.productcode = 'test pd code2two';
         testprod2.Approved__c = True;
         testprod2.CanUseRevenueSchedule = True;
         insert testprod2;
// Get Pricebook
         Pricebook2 testpb = [select id from Pricebook2 where IsStandard = true];
         update testpb;   
// Add to pricebook
        PriceBookEntry pbe1 = new PricebookEntry();
        pbe1.UnitPrice = 100;
        pbe1.Product2Id = testprod1.Id;
        pbe1.Pricebook2Id = testpb.id;
        pbe1.IsActive = true;
        pbe1.useStandardPrice = false;
        insert pbe1;
        PriceBookEntry pbe2 = new PricebookEntry();
        pbe2.UnitPrice = 200;
        pbe2.Product2Id = testprod2.Id; 
        pbe2.Pricebook2Id = testpb.id;
        pbe2.IsActive = true;
        pbe2.useStandardPrice = false;
        insert pbe2;


update Oppty1;
System.assertNotEquals('Prospecting', Oppty1.StageName); ***not sure if this part is even correct

  • 1
    What have you written so far? Where are you getting stuck?
    – tomlogic
    Feb 11 '13 at 16:31
  • I haven't written anything yet. I just started some Google searches to get me started in the meantime. I have VERY limited coding experience so most of what I write will be trial and error. Feb 11 '13 at 16:36
  • 6
    Take a look at An Introduction to Apex Code Test Methods, have a go, then come back with specific questions if you get stuck. Alternatively, you could ask over at the Force.com Discussion Boards. The discussion boards work better for these kind of open-ended questions.
    – metadaddy
    Feb 11 '13 at 16:50
  • I have edited my original post to include some test code I found and modified. Feb 11 '13 at 21:36

Pricebooks (and Products for that matter) seem to be copied over to sandboxes, even the developer ones. So I don't think you need to insert these PricebookEntry records? Also this info seems to be a bit discouraging:

Inserting a pricebook entry for a product isn’t feasible from a test since the standard pricebook isn’t accessible and can’t be created in a running test. Also, inserting a pricebook entry for a custom pricebook isn’t supported since this requires defining a standard pricebook. For such situations, annotate your test method with IsTest(SeeAllData=true) so that your test can access organization data.

So I'd say apply the annotation (ok, you already have it) and check what does this return: System.debug([select id from Pricebook2 where IsStandard = true]);

if it looks promising (returns some ids) - query SELECT Id, Pricebook2Id, Pricebook2.Name, Product2Id, Product2.Name FROM PricebookEntry and use these while adding OpportunityLineItems?

  • I will try playing with this a little. If I query the DB for an Id in Pricebook2 I get one record. I think I am still missing some lines in my code to actually add the products to the opportunity. Little by little I will figure this out. Thanks for your help. Feb 12 '13 at 14:31
  • 1
    You probably do have only 1 Pricebook. The point is that it might contain many items (entries) that are a link between pricebook and product. Is salesforce.com/us/developer/docs/api/Content/… of any help? Run this query, apologies for the typo in the answer SELECT Id, Pricebook2Id, Pricebook2.Name, Product2Id, Product2.Name FROM PricebookEntry
    – eyescream
    Feb 12 '13 at 14:47
  • Thanks will try that as well... need to figure out the code logic. Feb 12 '13 at 19:40

You want to test each probable code branch. It looks like you want to take the following into consideration:

  1. The test code must run as a non-administrator. You should either create a user with a different profile or query for one to use in your testing. Then use System.runAs to run the tests as the user.
  2. Your opportunity probability must be greater than 70%. When you create your test opportunity, you should make sure you give it a probability.
  3. Your opportunity can't have a prospect on it. You should try opps with and without these types of product.

Since you are adding an error to the opportunity, your test code needs a try...catch around your update Oppty1 to catch the error and confirm it is the one you are expecting to get back.

  • 2
    And as a side note on exception testing -- have a failing assert at the end of any try block that is supposed to fail. You'll catch test cases where there wasn't an exception when there should have been one (since your catch block won't run). I've seen this happen in multiple test methods -- you're so focused on making sure the correct exception is generated that you forget to test whether there was even an exception.
    – tomlogic
    Feb 12 '13 at 17:35
  • Thanks! That helps a lot! I will have to see if I can find similar examples for all of the above. Feb 12 '13 at 19:41

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.