function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Jesper Klang.Jesper Klang. 

Need help with a test class where I'm getting the error: System.SerializationException: Not Serializable: System.HttpRequest

Hi!

I'm doing a challenge where I need to get my test class to at least 90%. I'm currently getting the error message 'System.SerializationException: Not Serializable: System.HttpRequest'. I've searched around but can't figure out how to solve it.

Can someone be kind and have a look at my code?
global class ProjectCalloutService {
    
    global class QueueablePMSCall implements Queueable, Database.AllowsCallouts {
        HttpRequest req = new HttpRequest();
        Opportunity opp = new Opportunity();
        
        global QueueablePMSCall(HttpRequest req, ID oppId){
            this.req = req;
            this.opp.Id = oppId;
        }
        
        global void execute(QueueableContext context) {
            Http http = new Http();
			HttpResponse res = http.send(req);
            if (res.getStatusCode() == 201) {
                opp.StageName = 'Submitted Project';
                System.debug('Successfully submitted!');
            } else {
                opp.StageName = 'Resubmit Project';
                System.debug('Failed to submit! Error message: ' + res.getStatus());
            }
            update opp;
        }
    }
    
    @InvocableMethod(label='Post Opportunity To PMS' description='Posts the triggered Opportunity to the PMS system')
	public static void postOpportunityToPMS(List<ID> Opportunity_Id){
        ID oppId = Opportunity_Id[0];
        Opportunity opp = [SELECT Name, Account.Name, CloseDate, Amount FROM Opportunity WHERE ID = :oppId]; 
        HttpRequest req = new HttpRequest();
        req.setEndpoint('callout:ProjectService');
        req.setMethod('POST');
        req.setHeader('Content-Type', 'application/json');
        req.setHeader('token', ServiceTokens__c.getValues('ProjectServiceToken').Token__c);
        req.setBody('{"opportunityId": ' + opp.Id + 
                        ', "opportunityName": ' + opp.Name + 
                        ',"accountName": ' + opp.Account.Name + 
                        ', "closeDate": ' + opp.CloseDate + 
                        ',"amount": ' + opp.Amount + '}');
        QueueablePMSCall toQueue = new QueueablePMSCall(req, opp.Id);
        ID jobID = System.enqueueJob(toQueue);
        System.debug('jobID: ' + jobID);
    }
}
Test class:
@isTest
private class ProjectCalloutServiceTest {
  	@Testsetup static void TestSetup() {
        Account acc = new Account(Name = 'Jespers Account');
        insert acc;
        Opportunity opp1 = new Opportunity(Name = 'Opp1', 
                                          AccountId = acc.id, 
                                          CloseDate = Date.today(), 
                                          Amount = 1000, 
                                          StageName = 'Closed/Won',
                                          Type = 'New Project');
        insert opp1;
        Opportunity opp2 = new Opportunity(Name = 'Opp2', 
                                          AccountId = acc.id, 
                                          CloseDate = Date.today(), 
                                          Amount = 3000, 
                                          StageName = 'Closed/Won', 
                                          Type = 'New Project');
        insert opp2;
        ServiceTokens__c servToken = new ServiceTokens__c();
        servToken.Name = 'ProjectServiceToken';
        servToken.Token__c = 'qwertyuiopnjhgft';
        insert servToken;
    }
    
  	@isTest
    static void TestSuccess() {
        ID oppId = [SELECT Name FROM Opportunity WHERE Name = 'Opp1'].Id;
        List<ID> oppList = new List<ID>();
        oppList.add(oppId);
        Test.setMock(HttpCalloutMock.class, new ProjectCalloutServiceMock());
        Test.startTest();
        ProjectCalloutService.postOpportunityToPMS(oppList);
		Test.stopTest();
        String testOpp = [SELECT StageName FROM Opportunity WHERE ID = :oppId].StageName;
        System.assertEquals('Submitted Project', testOpp);
    }
    
  	@isTest
    static void TestFail() {
        ID oppId = [SELECT Name FROM Opportunity WHERE Name = 'Opp2'].Id;
        List<ID> oppList = new List<ID>();
        oppList.add(oppId);
        Test.startTest();
        Test.setMock(HttpCalloutMock.class, new ProjectCalloutServiceMockFailure());
        ProjectCalloutService.postOpportunityToPMS(oppList);
		Test.stopTest();
        String testOpp = [SELECT StageName FROM Opportunity WHERE ID = :oppId].StageName;
        System.assertEquals('Resubmit Project', testOpp);
    }
}
First Mock:
@isTest
global class ProjectCalloutServiceMock implements HttpCalloutMock{
    global HttpResponse respond(HttpRequest req) {
        HttpResponse res = new HttpResponse();
        res.setStatusCode(201);
        res.setStatus('OK');
        return res;
    }
}
Second Mock:
@isTest
global class ProjectCalloutServiceMockFailure implements HttpCalloutMock{
    global HttpResponse respond(HttpRequest req) {
        HttpResponse res = new HttpResponse();
        res.setStatusCode(500);
        res.setStatus('This is an error message!');
        return res;
    }
}
Best Answer chosen by Jesper Klang.
Alain CabonAlain Cabon
Hi Jesper,

Don't pass HttpRequest req as a parameter value for any method.
 
global class ProjectCalloutService {
    
    global class QueueablePMSCall implements Queueable, Database.AllowsCallouts {        
        Opportunity opp = new Opportunity();        
        global QueueablePMSCall(Opportunity opp){           
            this.opp = opp;
        }
        
        global void execute(QueueableContext context) {
            HttpRequest req = new HttpRequest();
            req.setEndpoint('callout:ProjectService');
            req.setMethod('POST');
            req.setHeader('Content-Type', 'application/json;charset=UTF-8');
            req.setHeader('token', ServiceTokens__c.getValues('ProjectServiceToken').Token__c);
            req.setBody('{"opportunityId": "' + opp.Id + 
                        '", "opportunityName": "' + opp.Name + 
                        '","accountName": "' + opp.Account.Name + 
                        '", "closeDate": "' + opp.CloseDate + 
                        '","amount": ' + opp.Amount + '}');
            Http http = new Http();
            HttpResponse res = http.send(req);
            if (res.getStatusCode() == 201) {
                opp.StageName = 'Submitted Project';
                System.debug('Successfully submitted!');
            } else {
                opp.StageName = 'Resubmit Project';
                System.debug('Failed to submit! Error message: ' + res.getStatus());
            }
            update opp;
        }
    }
    
    @InvocableMethod(label='Post Opportunity To PMS' description='Posts the triggered Opportunity to the PMS system')
    public static void postOpportunityToPMS(List<ID> Opportunity_Id){
        ID oppId = Opportunity_Id[0];
        Opportunity opp = [SELECT Name, Account.Name, CloseDate, Amount FROM Opportunity WHERE ID = :oppId]; 
        
        QueueablePMSCall toQueue = new QueueablePMSCall(opp);
        
        ID jobID = System.enqueueJob(toQueue);
        System.debug('jobID: ' + jobID);
    }
}

By the way, fixed JSON code for req.setBody.

Alain

All Answers

Alain CabonAlain Cabon
Hi Jesper,

Don't pass HttpRequest req as a parameter value for any method.
 
global class ProjectCalloutService {
    
    global class QueueablePMSCall implements Queueable, Database.AllowsCallouts {        
        Opportunity opp = new Opportunity();        
        global QueueablePMSCall(Opportunity opp){           
            this.opp = opp;
        }
        
        global void execute(QueueableContext context) {
            HttpRequest req = new HttpRequest();
            req.setEndpoint('callout:ProjectService');
            req.setMethod('POST');
            req.setHeader('Content-Type', 'application/json;charset=UTF-8');
            req.setHeader('token', ServiceTokens__c.getValues('ProjectServiceToken').Token__c);
            req.setBody('{"opportunityId": "' + opp.Id + 
                        '", "opportunityName": "' + opp.Name + 
                        '","accountName": "' + opp.Account.Name + 
                        '", "closeDate": "' + opp.CloseDate + 
                        '","amount": ' + opp.Amount + '}');
            Http http = new Http();
            HttpResponse res = http.send(req);
            if (res.getStatusCode() == 201) {
                opp.StageName = 'Submitted Project';
                System.debug('Successfully submitted!');
            } else {
                opp.StageName = 'Resubmit Project';
                System.debug('Failed to submit! Error message: ' + res.getStatus());
            }
            update opp;
        }
    }
    
    @InvocableMethod(label='Post Opportunity To PMS' description='Posts the triggered Opportunity to the PMS system')
    public static void postOpportunityToPMS(List<ID> Opportunity_Id){
        ID oppId = Opportunity_Id[0];
        Opportunity opp = [SELECT Name, Account.Name, CloseDate, Amount FROM Opportunity WHERE ID = :oppId]; 
        
        QueueablePMSCall toQueue = new QueueablePMSCall(opp);
        
        ID jobID = System.enqueueJob(toQueue);
        System.debug('jobID: ' + jobID);
    }
}

By the way, fixed JSON code for req.setBody.

Alain
This was selected as the best answer
Jesper Klang.Jesper Klang.
Thanks alot Alain! Works like a charm. Couldn't find a reason why you can't pass a HttpRequest, but now I know that was the issue. Thanks for the JSON change as well. Sometimes it's good with a couple of extra eyes :)