3

Why when I try to deploy my class is it saying that the code coverage is 0%. I don't understand what I need to do for the class to pass? I set up a change set with the two classes below, and when i click validate > run specific tests > "TEST_OpOwnerConvertedServiceNotif" it says the code coverage is 0%.

I have clicked "Run Test" within the test class and it passes, what more do I need to do?

When I'm in the developer console in the class, it also says that code coverage is "None"

Below is my test class:

@istest private class TEST_OpOwnerConvertedServiceNotif 
{
    static testMethod void TEST_OpOwnerConvertedServiceNotif ()
    {
        Account acc = new Account(Name = 'Test Account');
        insert acc;

        ID pricebookId = Test.getStandardPricebookId();

        Product2 prd1 = new Product2(
            Name = 'Test Product Entry 1',
            Description = 'Test Product Entry 1',
            productCode = 'ABC', isActive = false,
            RecordTypeId = '0128E0000004m8b',
            R_D_Service_Owner__c = '005w0000004x3RiAAI',
            Convert_to_Service_Catalogue_Initiated__c = TRUE,
            Convert_to_Service_Catalogue_Emailed__c = FALSE
        );
        insert prd1;

        PricebookEntry pbe1 = new PricebookEntry(
            Product2ID=prd1.id, 
            Pricebook2ID = pricebookId,
            UnitPrice=0, 
            isActive=true
        );
        insert pbe1;

        Opportunity opp1 = new Opportunity(
            Name='Opp1', 
            StageName='Proposal Accepted', 
            CloseDate=Date.today(),
            Pricebook2Id = pbe1.Pricebook2Id, 
            AccountId = acc.id
        ); 
        insert opp1;

        OpportunityLineItem lineItem1 = new OpportunityLineItem(
            OpportunityID = opp1.id, 
            PriceBookEntryID = pbe1.id, 
            quantity=1, 
            totalprice=0
        );
        insert lineItem1;

        Test.startTest();

        Test.stopTest();
    }
}

Below is the class related to the test:

global class OpOwnerConvertedServiceNotif Implements Schedulable
//If an R&D Service or project is converted to a full service record, when  it is already attached to an opportunity, a notification will be sent to the opportunity owner, informing them of the change
{
    global void execute (SchedulableContext sc)
    {
        sendConvertedEmailToOppOwner();
    }
    public void sendConvertedEmailToOppOwner()
    {
        List<Opportunity> listOpportunity = new List <Opportunity>();
        listOpportunity = [
            SELECT Id, OwnerId,Name,Owner.FirstName,
                (SELECT Id, Product2.Name FROM OpportunityLineItems
                    WHERE Product2.Convert_to_Service_Catalogue_Emailed__c = FALSE
                        AND Product2.Convert_to_Service_Catalogue_Initiated__c = TRUE)
            FROM Opportunity
            WHERE StageName != 'Closed Won - Signed Contract' AND StageName != 'Closed Lost' AND Id in
                (SELECT OpportunityId 
                FROM OpportunityLineItem
                WHERE Product2.Convert_to_Service_Catalogue_Emailed__c = FALSE
                    AND Product2.Convert_to_Service_Catalogue_Initiated__c = TRUE)
        ];

        for(Opportunity opp :listOpportunity)
        {
            List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();
            {

                Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();

                email.setTargetObjectId(opp.OwnerId);
                email.setReplyTo('glenn.daly@live.com');
                email.setSenderDisplayName('Salesforce Support');
                for(opportunitylineitem oppLineItem:opp.opportunitylineitems)
                    email.setSubject('An R&D service or project attached to an opportunity owned by you has been progressed to a live service');
                    String body ='Hi ' + opp.Owner.FirstName + ',';
                    body += '<br><br>Salesforce recognises you as the owner of the following opportunity: ' + opp.Name;
                for(opportunitylineitem oppLineItem:opp.opportunitylineitems)
                    body += '<br><br>Attached to this opportunity is an R&D service or project:'+oppLineItem.Product2.Name + '. This service or project has been progressed to a live service, so is no longer available.';
                    body += '<br><br>Please use the link below to update the opportunity';
                    body += '<br><br>test.salesforce.com/'+opp.id;
                    email.setHtmlBody(body);
                    email.setSaveAsActivity(false);
                    emails.add(email);
             }
            Messaging.sendEmail(emails);

            update listOpportunity;
        }
        Map<Id,Product2> products = new Map<Id, Product2>();
        for(Opportunity opp: listOpportunity){
            for(OpportunityLineItem oppLineItem: opp.opportunitylineitems){
                products.put(oppLineItem.Product2Id, new Product2(Id=oppLineItem.Product2Id, Convert_To_Service_Catalogue_Emailed__c = TRUE));
            }
         }
         update products.values();       
     }
}
5
  • I don't understand. You don't call your schedulable class in your test class. – Martin Lezer Jan 17 '17 at 10:34
  • @MartinLezer so what have I done wrong in the code? – Glenn Daly Jan 17 '17 at 10:36
  • 2
    you need to call your scheduleable class between the Test.startTest() and Test.stopTest() – RCS Jan 17 '17 at 10:38
  • 3
    Don't use the global access modifier. Also every test method should contain assertions. – Adrian Larson Jan 17 '17 at 10:42
  • 1
    I've completely overhauled the formatting of your provided code. Being consistent with indentation is important for readability (because having hard to read code can discourage people from answering). In doing so, it appears that you have some syntax errors (unterminated for loops) and a few other issues (dml in a for loop). – Derek F Jan 17 '17 at 14:35
4

Add below piece of code between the Test.startTest and Test.stopTest

Test.startTest();
  OpOwnerConvertedServiceNotif sobj = new OpOwnerConvertedServiceNotif();
  system.schedule('Scheduable_Class', '0 0 23 * * ?', sobj); //'0 0 23 * * ?' is the time frame when do you want to schedule the class
Test.stopTest();
4
  • This is correct for gaining code coverage, but neglects the fact that the unit test does not have any assertions. – Derek F Jan 17 '17 at 14:38
  • This is just the code snippet that will cover the schedule class it's not the full test method – RCS Jan 17 '17 at 15:57
  • 1
    I understand that, I just don't like encouraging people to do the bare minimum required to make a deployment work. Unit tests (and the SF enforced code coverage) are meaningless without assertions. Salesforce can't possibly determine what you meant for your code to do, so the only metric they can use is coverage. Code coverage is simply a side product of unit testing, the real purpose of unit tests is to ensure that your logic behaves the way you expect it to. Hence, a unit testing answer that neglects assertions is an incomplete answer in my mind. – Derek F Jan 17 '17 at 16:02
  • I totally agree with you – RCS Jan 17 '17 at 16:11

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.