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
Leafen SandyLeafen Sandy 

Test class for api having attachments in container

@RestResource(urlMapping='/Merchandise/*')
global with sharing class MerchandiseResource {

private class Attach {
    String Body;
    String ContentType;
    String Name;
}
private class Merchandise {
    Merchandise__c merchandise;
    list<Attach> attachments;
} 

@HttpPost
global static String doPost() {
    //json will be taken directly from RestContext
    Merchandise container = (Merchandise)System.JSON.deserialize(
        RestContext.request.requestBody.tostring(), 
        Merchandise.class);

    Merchandise__c merch = container.merchandise;
    insert merch;

    list<attachment> attachmentToInsert = new list<attachment>();

    for (Attach att :container.attachments) {
        attachmentToInsert.add(
            new Attachment(parentId = merch.Id, name = att.name, 
                           ContentType = att.ContentType, 
                           Body = EncodingUtil.base64Decode(att.body)));
    }
    insert attachmentToInsert;

    return merch.id;
}}

Can anyone suggest me a test class for this above code.
I send the following json.
 
{
    "merchandise": {
        "Name": "Eraser"
    },
    "attachments": [{
        "Body": "d29ybGQ=",
        "ContentType": "text/plain",
        "Name": "hello.txt"
    }, {
        "Body": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAMSURBVBhXY3growIAAycBLhVrvukAAAAASUVORK5CYII=",
        "ContentType": "image/png",
        "Name": "picture.png"
    }]
}


I also tried the below test class,
 
@isTest
public class TesMerchandiseResource 
 {
    
     private Static testMethod void testFunction()
     {


System.RestContext.request = new RestRequest();
        System.RestContext.response = new RestResponse();
        RestContext.request.requestBody =blob.valueof('{}');

		
		 Account accountDetails = new Account();
        accountDetails.name = 'test name';
        upsert accountDetails;
		
 Attachment attachIt = new Attachment();
        attachIt.Name = 'test_attch';
        attachIt.ParentId = accountDetails.id;
        Blob bodyBlob=Blob.valueOf('Unit Test Attachment Body');
      attachIt.body=bodyBlob;
	  
	   RestContext.request.requestBody =blob.valueof('{     "merchandise": {         "Name": "Eraser"     },     "attachments": [{         "Body": "d29ybGQ=",         "ContentType": "text/plain",         "Name": "hello.txt"     }, {         "Body": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAMSURBVBhXY3growIAAycBLhVrvukAAAAASUVORK5CYII=",         "ContentType": "image/png",         "Name": "picture.png"     }] }');
        MerchandiseResource .doPost();

}

}

Still I get error "Attempt to de-reference a null object" in the line ​"for (Attach att :container.attachments) {"

Thanks in Advance,
Leafen.
 
Best Answer chosen by Leafen Sandy
Amit Chaudhary 8Amit Chaudhary 8
Hi Leafen,

I just converted your API from merchant to Account and tested in my org which is working perfectly.
Apex Class.
@RestResource(urlMapping='/Merchandise/*')
global with sharing class MerchandiseResource {

private class Attach {
    String Body;
    String ContentType;
    String Name;
}
private class Merchandise {
    Account merchandise;
    //Merchandise__c merchandise;
    list<Attach> attachments;
} 

@HttpPost
global static String doPost() {
    //json will be taken directly from RestContext
        Merchandise container = (Merchandise)System.JSON.deserialize(
        RestContext.request.requestBody.tostring(), 
        Merchandise.class);

    Account merch = container.merchandise;
    //Merchandise__c merch = container.merchandise;
    insert merch;

    list<attachment> attachmentToInsert = new list<attachment>();

    for (Attach att :container.attachments) {
        attachmentToInsert.add(
            new Attachment(parentId = merch.Id, name = att.name, 
                           ContentType = att.ContentType, 
                           Body = EncodingUtil.base64Decode(att.body)));
    }
    insert attachmentToInsert;

    return merch.id;
}}

Test Class.
@isTest
public class TesMerchandiseResource 
 {
    
     private Static testMethod void testFunction()
     {


        System.RestContext.request = new RestRequest();
        System.RestContext.response = new RestResponse();
        RestContext.request.requestBody =blob.valueof('{}');
        RestContext.request.requestBody =blob.valueof('{     "merchandise": {         "Name": "Eraser"     },     "attachments": [{         "Body": "d29ybGQ=",         "ContentType": "text/plain",         "Name": "hello.txt"     }, {         "Body": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAMSURBVBhXY3growIAAycBLhVrvukAAAAASUVORK5CYII=",         "ContentType": "image/png",         "Name": "picture.png"     }] }');
       
        MerchandiseResource.doPost();

    }

}


Look like some issue is coming while inserting the Merchandise__c  record.

  Merchandise__c merch = container.merchandise;
  insert merch;

I hope you are passing all required field.

Can you please post full error

All Answers

Amit Chaudhary 8Amit Chaudhary 8
Hi Leafen,

I just converted your API from merchant to Account and tested in my org which is working perfectly.
Apex Class.
@RestResource(urlMapping='/Merchandise/*')
global with sharing class MerchandiseResource {

private class Attach {
    String Body;
    String ContentType;
    String Name;
}
private class Merchandise {
    Account merchandise;
    //Merchandise__c merchandise;
    list<Attach> attachments;
} 

@HttpPost
global static String doPost() {
    //json will be taken directly from RestContext
        Merchandise container = (Merchandise)System.JSON.deserialize(
        RestContext.request.requestBody.tostring(), 
        Merchandise.class);

    Account merch = container.merchandise;
    //Merchandise__c merch = container.merchandise;
    insert merch;

    list<attachment> attachmentToInsert = new list<attachment>();

    for (Attach att :container.attachments) {
        attachmentToInsert.add(
            new Attachment(parentId = merch.Id, name = att.name, 
                           ContentType = att.ContentType, 
                           Body = EncodingUtil.base64Decode(att.body)));
    }
    insert attachmentToInsert;

    return merch.id;
}}

Test Class.
@isTest
public class TesMerchandiseResource 
 {
    
     private Static testMethod void testFunction()
     {


        System.RestContext.request = new RestRequest();
        System.RestContext.response = new RestResponse();
        RestContext.request.requestBody =blob.valueof('{}');
        RestContext.request.requestBody =blob.valueof('{     "merchandise": {         "Name": "Eraser"     },     "attachments": [{         "Body": "d29ybGQ=",         "ContentType": "text/plain",         "Name": "hello.txt"     }, {         "Body": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAMSURBVBhXY3growIAAycBLhVrvukAAAAASUVORK5CYII=",         "ContentType": "image/png",         "Name": "picture.png"     }] }');
       
        MerchandiseResource.doPost();

    }

}


Look like some issue is coming while inserting the Merchandise__c  record.

  Merchandise__c merch = container.merchandise;
  insert merch;

I hope you are passing all required field.

Can you please post full error
This was selected as the best answer
Leafen SandyLeafen Sandy
Hi Amit,
 Thanks for your reply.

But is your test class able to cover the class because,
I dont have any problem with my api class, but when I try to run my test class it is not covering from  for (Attach att :container.attachments) loop, line 26.
In my catch I get exception message as "Attempt to de reference null object" in the for loop line.

Can you help me on the test class coverage. 
Thanks again.
Leafen.
 
Amit Chaudhary 8Amit Chaudhary 8
I got 100% code coverage. Can you please add the debug log and share full error log. So that we can check which variable is null ?
Leafen SandyLeafen Sandy
Amit,

Now my api class is covering, I just blindly pasted your test class.
Not sure what was the significant difference between our test classes. However now I dont need to bother much.

Anyways thanks for your time.
Leafen.