Apex测试类调用getContent方法报错,请求解决方案
解决Apex测试类调用
getContent报错的方案 问题根源
Salesforce的测试方法(@isTest标注的方法)不支持直接调用PageReference.getContent()或getContentAsPDF(),这是平台的上下文限制——测试环境无法实际渲染Visualforce页面生成PDF,因此执行到该方法时会抛出断言错误。
解决方案
下面提供两种实用的解决方式,可根据代码结构选择:
方案1:使用Mock类隔离PDF生成逻辑(推荐)
核心思路是将PDF生成方法设计为可重写的,在测试中用Mock类替代实际的PDF渲染逻辑,专注于验证邮件发送的业务流程。
1. 修改原Apex类
将getPdfFileAsBase64String改为virtual方法,允许测试类重写:
public class ApexParser { // 改为virtual方法,方便测试重写 public virtual String getPdfFileAsBase64String(Id recordId) { PageReference pdfPage = Page.YourPdfPage; // 替换为你的实际页面 pdfPage.getParameters().put('id', recordId); Blob pdfBlob = pdfPage.getContent(); return EncodingUtil.base64Encode(pdfBlob); } public void sendEmailTemplate(Id targetContactId, Id recordId) { String pdfBase64 = getPdfFileAsBase64String(recordId); // 组装邮件附件 Messaging.EmailFileAttachment attachment = new Messaging.EmailFileAttachment(); attachment.setFileName('RecordDocument.pdf'); attachment.setBody(EncodingUtil.base64Decode(pdfBase64)); attachment.setContentType('application/pdf'); // 组装并发送邮件(省略具体邮件逻辑) Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage(); email.setTargetObjectId(targetContactId); email.setFileAttachments(new List<Messaging.EmailFileAttachment>{attachment}); Messaging.sendEmail(new List<Messaging.SingleEmailMessage>{email}); } }
2. 编写测试类及Mock实现
@isTest private class ApexParserTest { // 内部Mock类,重写PDF生成方法返回模拟数据 private class MockApexParser extends ApexParser { public override String getPdfFileAsBase64String(Id recordId) { // 返回模拟的Base64字符串,避免调用getContent return EncodingUtil.base64Encode(Blob.valueOf('Mock PDF Content for Testing')); } } @isTest static void testSendEmailTemplate() { // 准备测试数据 Contact testContact = new Contact(LastName='Test', Email='test@example.com'); insert testContact; Account testRecord = new Account(Name='Test Account'); insert testRecord; // 使用Mock类执行测试 MockApexParser parser = new MockApexParser(); Test.startTest(); parser.sendEmailTemplate(testContact.Id, testRecord.Id); Test.stopTest(); // 验证邮件发送结果 List<Messaging.SingleEmailMessage> sentEmails = [SELECT Id, ToAddresses, FileAttachments FROM Messaging.SingleEmailMessage]; System.assertEquals(1, sentEmails.size(), '应发送1封邮件'); System.assertEquals(testContact.Email, sentEmails[0].ToAddresses[0], '收件人邮箱匹配'); System.assertEquals(1, sentEmails[0].getFileAttachments().size(), '应包含1个附件'); System.assertEquals('RecordDocument.pdf', sentEmails[0].getFileAttachments()[0].getFileName(), '附件名称匹配'); } }
方案2:在生产代码中加入测试环境判断
如果无法修改原类的方法结构,可直接在getPdfFileAsBase64String中通过Test.isRunningTest()判断环境,测试时返回模拟数据:
修改原类方法
public class ApexParser { public String getPdfFileAsBase64String(Id recordId) { // 测试环境下返回模拟数据 if (Test.isRunningTest()) { return EncodingUtil.base64Encode(Blob.valueOf('Mock PDF Content')); } // 生产环境正常执行PDF生成逻辑 PageReference pdfPage = Page.YourPdfPage; pdfPage.getParameters().put('id', recordId); Blob pdfBlob = pdfPage.getContent(); return EncodingUtil.base64Encode(pdfBlob); } // sendEmailTemplate方法保持不变 }
测试类直接调用
此时测试类无需额外Mock,直接实例化原类即可执行测试,不会触发getContent调用:
@isTest private class ApexParserTest { @isTest static void testSendEmailTemplate() { // 准备测试数据(同方案1) Contact testContact = new Contact(LastName='Test', Email='test@example.com'); insert testContact; Account testRecord = new Account(Name='Test Account'); insert testRecord; ApexParser parser = new ApexParser(); Test.startTest(); parser.sendEmailTemplate(testContact.Id, testRecord.Id); Test.stopTest(); // 验证逻辑(同方案1) List<Messaging.SingleEmailMessage> sentEmails = [SELECT Id FROM Messaging.SingleEmailMessage]; System.assertEquals(1, sentEmails.size()); } }
方法对比
- 方案1(Mock):符合测试最佳实践,隔离了PDF渲染的依赖,测试聚焦于邮件发送逻辑,不受页面变更影响。
- 方案2(环境判断):实现简单,但会在生产代码中混入测试逻辑,不够优雅。
额外说明
如果需要验证PDF渲染的正确性,无法通过单元测试实现,需通过手动测试或集成测试工具(如Salesforce DX的无头浏览器测试)完成。
内容的提问来源于stack exchange,提问作者Jhony
相关产品推荐
相关产品推荐

