You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 15:52:45