0

I have the following trigger which gives a red flag in the development console on the addError line, how do i remove this with the unittest?

Trigger

trigger NoteOnContentDocument on ContentDocument (before delete) {
    for (ContentDocument c : Trigger.old){          
        List<ContentDocumentLink> links = [SELECT LinkedEntityId FROM ContentDocumentLink 
                                           WHERE ContentDocumentId= :c.Id];       
        if (!links.isEmpty() && Approval.isLocked(links.get(0).LinkedEntityId)){
            c.addError('Approval pending. You do not have the permission to edit/delete this note, please contact your administrator.');     
        }   
    }
}

Test Class

@istest
public class TestNoteOnContentDocuments {
    static testmethod void NoteOnContentDoc(){
        ContentVersion contentVersion = new ContentVersion(
            Title = 'Penguins',
            PathOnClient = 'Penguins.jpg',
            VersionData = Blob.valueOf('Test Content'),
            IsMajorVersion = true
        );
        insert contentVersion;    
        List<ContentDocument> documents = [SELECT Id, Title, LatestPublishedVersionId FROM ContentDocument];
        try{delete documents[0];
            system.assert(true);
           }            
        catch(DmlException e){
            System.Assert(e.getMessage().contains('Approval pending. You do not have the permission to edit/delete this note, please contact your administrator.'));   
        }
    }
}
  • 4
    You need links to be not empty...and for the linked entity to be locked. Neither of those seem to be the case. Your assertion pattern on the try/catch also needs an overhaul. At least change system.assert(true) to system.assert(false). – Adrian Larson Jan 20 '17 at 18:07
0

This is following way you could write the class and scenario.

To apply locking from apex code, choose the checkbox Enable record locking and unlocking in Apex as true, upon navigating Setup->Create-> Workflows and Approvals -> Process Automation Settings

Enable locking from Apex

  1. Create an account or any record.
  2. Create ContentVersion record
  3. Create ContentDocumentLink record using Account as Parent.
  4. Lock the Account record.
  5. Try to delete ContentDocument
  6. System will throw the exception.
  7. You can also verify the error message by Apexpages.Message

Definitely you will get 100% coverage.

@istest
public class TestNoteOnContentDocuments {
  static testmethod void NoteOnContentDoc()
  {
    List<Apexpages.Message> msgs;

    //create testUser 

    System.runAs(testUser)
    {
        //create an account 
        Account acct = new Account(Name='TEST_ACCT');
        insert acct;

        ContentVersion contentVersion = new ContentVersion(
          Title = 'Penguins',
          PathOnClient = 'Penguins.jpg',
          VersionData = Blob.valueOf('Test Content'),
          IsMajorVersion = true
        );
        insert contentVersion;    
        List<ContentDocument> documents = [SELECT Id, Title, LatestPublishedVersionId FROM ContentDocument];

        //create ContentDocumentLink  record for that account
        ContentDocumentLink cdl = New ContentDocumentLink(
                    LinkedEntityId = acct.id, ContentDocumentId = documents[0].Id, shareType = 'V');
        insert cdl;

        List<Account> accts = [SELECT Id from Account WHERE Name = 'TEST_ACCT'];

        //lock the account record.
        Approval.LockResult[] lrList = Approval.lock(accts, false);

        Test.startTest();
        try { delete documents; }
        catch (Exception dmx) 
        { 
           Boolean expectedExceptionThrown = dmx.getMessage().contains('Approval pending. You do not have the permission to edit/delete this note/attachment, please contact your administrator.') ? true : false; 
           System.assertEquals(expectedExceptionThrown, true);  
        }

        //Also it can tested like this through Apexpages.Message

        List<Apexpages.Message> msgs;
        msgs = ApexPages.getMessages();
            boolean isErrorMessage = false;
            for(ApexPages.Message msg : msgs)
            {
                if (msg.getSummary().contains('Approval pending.') )
                {
                    isErrorMessage  = true;
                }
            }
        System.debug('testing messages');
        System.assert(isErrorMessage);

        Test.stopTest();
    }

}
  • THANKS!! Got it working there was only a field missing on the create account:Account acct = new Account(Name='TEST_ACCT',Account_Status_DS__c = 'status'); – Eager 2 Learn apex Jan 22 '17 at 15:45
1

So your test is actually failing, but you did not write it correctly. Right now, if you do not get any DmlException, you have no assertion. At the very least, you would need to assert that you don't execute the rest of the try block:

try
{
    delete someRecords;
    system.assert(false, 'The operation should fail');
}

However, I really loathe conditional assertions of any kind. Write your test methods so that every assertion gets hit every time the test is run.

DmlException expectedException;
try
{
    delete someRecords;
}
catch (DmlException d)
{
    expectedException = d;
}

system.assertNotEquals(null, expectedException,
    'There should be a validation error');
system.assertEquals(someRecords.size(), [SELECT count() FROM MyObject__c],
    'The records should not be deleted');

Note that I assert on the records being in the database. This information is much more useful than the content of the exception message. Don't assert on that. It's an implementation detail and doesn't really matter.

So all of the above just tells you how to write a test that fails properly. Once you get this far, you will see that the records you are trying to delete do, in fact, get deleted. So now you need to set up your records so they will fulfill the validation criteria. The locking is easy now that you can just call Approval.lock(someRecords). But you need to create some ContentDocumentLink records and associate them to the ContentDocument records you want to delete.

Note that you have not properly bulkified your trigger. If you try to delete more than 100 records, you will hit a LimitException, because you have a query in a loop. Read up on General trigger bulkification - best practices

  • Thanks for explaining Adrian. I am still new on this, does this mean 'try{delete documents[0];' is correct, and what would expectedException be in this case? @Adrian – Eager 2 Learn apex Jan 21 '17 at 15:16

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.