5

I am using AgentWork trigger in my logic and I cannot achieve code coverage goal.

Simple test method:

Id cId = [SELECT Id From Case Where Subject = 'Case Subject'].Id;
User u = [SELECT Id From User LIMIT 1];
ServiceChannel sc = [SELECT Id FROM ServiceChannel WHERE DeveloperName = 'Service_Channel_Test' LIMIT 1];

System.runAs(u)
{
    List<AgentWork> agentWorks = new List<AgentWork>();
    agentWorks.add(new AgentWork(WorkItemId = cId, UserId = u.Id, ServiceChannelId = sc.Id));

insert agentWorks;

}

returns

System.DmlException: Insert failed. First exception on row 0; first error: FIELD_INTEGRITY_EXCEPTION, The agent's status is not associated with the channel for this work.: [ServiceChannelId]

Because of manipulation of UserServicePresence is not permitted then I cannot move forward. I suppose that, currently it is not supported by SFDC. Which is funny because test coverage is obligatory.

Do you have any experience with AgentWork unit tests?

  • This is a very interesting question that hasn't been discussed much online. Has anybody found a solution? – feddus Feb 19 '16 at 9:10
  • Does it helps : developer.salesforce.com/forums/?id=906F00000005KVYIA2 ------- See comments – Salesforce Steps Feb 22 '16 at 15:24
  • 1
    @SalesforceSteps I tried everything on the link. It doesn' help. – Saumya Gaikwad Aug 28 '19 at 6:22
  • @SaumyaGaikwad I always wanted to answer this, but it skipped my mind. Thanks for bounty which made me remeber writing solution. Our org had recent OmniChannel implementation and this is how I managed to solve. – Pranay Jaiswal Aug 28 '19 at 13:31
  • Solution is simple. Don't have a Trigger on AgentWork. Use Process Builder to execute the code you need to run. – dBeltowski Aug 30 '19 at 15:17
1

This is a very interesting scenario, which everyone faced while testing/deploying omnichannel. Inserting is not allowed and as manish porwal suggested you have to make test running user as active on OmniChannel to get coverage for AgentWorkTrigger. This makes unit testing hard and impossible for CI/CD as someone has to manually go and make test running user as active to test class to pass.

So the requirement boils down to:

1) How to achieve some coverage on AgentWork Trigger?

2) How to unitest them without inserting then?

The logic lies in beforeInsert trigger, consider the order of execution:

The key point to note here is, in insert the before insert trigger runs first and then the system validation steps.

The exception you mentioned:

: Insert failed. First exception on row 0; first error: FIELD_INTEGRITY_EXCEPTION, The agent's status is not associated with the channel for this work.: [ServiceChannelId]

happens after the before insert trigger, thus if you catch that, you can have some coverage in trigger thus it can be deployed without making any user as active in OmniChannel.

Things get simpler if you write a single line trigger and make your handler do everything:

trigger AgentWorkTrigger on AgentWork (before insert, after update) {

    AgentWorkTriggerHandler.run();

}

public class AgentWorkTriggerHandler{

    public static void run(){

        switch on Trigger.operationType {
            when BEFORE_INSERT {
                System.debug('Before Insert'); //For Test
            }
            when AFTER_UPDATE {
                agentWorkService.doMyLogic(Trigger.new);//Your Service method
            }
        }

    }

}

Now to test trigger for coverage

@isTest
private static testTriggerCoverage(){

ServiceChannel sc = [SELECT Id
                FROM ServiceChannel WHERE DeveloperName = 'TestUnit'
                LIMIT 1];
Case caseRec = [SELECT Id FROM Case LIMIT 1];
User systemUser = [SELECT Id FROM User WHERE FirstName = 'System'];


System.runAs(systemUser){
    //Try Catch is to ensure test doesn't fail in cisit and ciuat
    try{
        AgentWork aw = new AgentWork(
                ServiceChannelId = sc.Id,
                WorkItemId = caseRec.Id,
                UserId = systemUser.Id
        );
        insert aw;

        aw.MyField__c = 'Submitted';
        update aw;
    }catch(Exception ex){
        //Exception will occur due to the omni channel bug. Ignore it

}

}

Here, I am catching the exception to have some coverage for AgentTrigger

Now you code logic now exists in Handlers/Service methods, thus you can mock Trigger.new, old, newMap,Oldmap and send it to your service methods and get them covered.

Resources: https://developer.salesforce.com/forums/?id=906F00000005KVYIA2

| improve this answer | |
  • Annotate your run method with @InvocableMethod and call it from Process Builder. Then you won't need the AgentWork trigger at all. – dBeltowski Aug 30 '19 at 15:20
  • You saved the day; thanks! – Willem Mulder Jun 24 at 19:06
  • @WillemMulder happy to help. This gave me many sleepless nights .:) – Pranay Jaiswal Jun 25 at 19:42
  • Yes, because if this didn't work, the Trigger would not deploy at all. Ever. Because it needs > 0% coverage :-( So thanks again!! :-D – Willem Mulder Jun 26 at 8:21
0

I have faced the similar situation in my test class related to AgenWorkTrigger. To have a successful run for the test class, the logged in user should be available on the omnichannel and after that test class should be run.

| improve this answer | |
0

My solution was to simply NOT HAVE AN AGENT WORK TRIGGER!

Put all your logic in a separate class. Now annotate the entry method with @InvocableMethod and call that method from the Process Builder.

BAM! No more AgentWork trigger, no more requirements for test coverage, no more errors about FIELD_INTEGRITY ServiceChannelId bunk, no more logging into Omni-Channel during deployments.

You can test your InvocableMethod without actually inserting or updating AgentWork.

Example Helper Class

public class AgentworkTriggerHelper
{
    @InvocableMethod
    public static void agentworkStatusUpdate(List<AgentWork> newAgentWorkList)
    {
        ... your logic here ...
    }
}

Example Test Class

public class AgentworkTriggerHelperTest
{
    @isTest static void agentWork()
    {
        AgentWork aw = new AgentWork();
        aw.serviceChannelId = schannel.Id;

        List<AgentWork> aworksList = new List<AgentWork>{aw};

        AgentworkTriggerHelper.agentworkStatusUpdate(aworksList);
    }
{
| improve this answer | |

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.