---
schema_version: "1"
id: c8b0ef5ca0ed9467f0c1ef5df246cf6c3b4c99d52d560ddc4eb665b97fbd0492
title: External Change Data Capture Packaging and Testing
collection: legacydeveloper
version: current
locale: en-us
portal_url: https://docs.salesforce.com/legacydeveloper/current/en-us/apexcode/apex_connector_external_tracking_package_and_test.md
canonical_url: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_connector_external_tracking_package_and_test.htm
source_site: developer.salesforce.com
content_type: documentation
content_hash: 8ece502ba7a16f0f2cadf87caaed6ed9cd999f4d514af771c10c2721ab579528
description: You can distribute External Change Data Capture components in managed packages, including a framework for testing your Apex triggers. Special behaviors and limitations apply to packaging and package installation.
---
# External Change Data Capture Packaging and Testing

You can distribute External Change Data Capture components in managed packages, including a framework for testing your Apex triggers. Special behaviors and limitations apply to packaging and package installation.

- Include External Change Data Tracking components in a managed package by selecting your test from the Apex Class Component Type list. The trigger, test, external data source, external object, and other related assets are brought into the package for distribution.
- Certificates aren’t packageable. If you package an external data source that specifies a certificate, make sure that the subscriber org has a valid certificate with the same name.

To help you test your External Change Data Capture–triggered Apex classes, here is a unit test code example of a trigger reacting to a simulated external change.

**Example Trigger**

​trigger OnExternalProductChangeEventForAudit on Products\_\_ChangeEvent (after insert) {
    if (Trigger.new.size() != 1) return;
    for (Products\_\_ChangeEvent event: Trigger.new) {
         Product\_Audit\_\_c audit = new Product\_Audit\_\_c(); 
         audit.Name = 'ProductChangeOn' + event.ExternalId;
         audit.Change\_Type\_\_c = event.ChangeEventHeader.getChangeType();
         audit.Audit\_Price\_\_c = event.Price\_\_c;
         audit.Product\_Name\_\_c = event.Name\_\_c;
         insert(audit);
    }
}

**Apex Test**

​@IsTest
public with sharing class testOnExternalProductChangeEventForAudit {
    @IsTest
    static void testExternalProductChangeTrigger() { 
            // Create Change Event
           Products\_\_ChangeEvent event = new Products\_\_ChangeEvent();
            // Set Change Event Header Fields
           EventBus.ChangeEventHeader header = new EventBus.ChangeEventHeader();
           header.changeType='CREATE';
           header.entityName='Products\_\_x';
           header.changeOrigin='here';
           header.transactionKey = 'some';
           header.commitUser = 'me';
           event.changeEventHeader = header;
           event.put('ExternalId', 'ParentExternalId');
           event.put('Price\_\_c', 5500);
           event.put('Name\_\_c', 'Coat');
            // Publish the event to the EventBus
           EventBus.publish(event);
           Test.getEventBus().deliver();
            // Perform assertion that the trigger was run
           Product\_Audit\_\_c audit = \[SELECT name, Audit\_Price\_\_c, Product\_Name\_\_c FROM Product\_Audit\_\_c WHERE name = : 'ProductChangeOn'\+ event.ExternalId WITH USER\_MODE LIMIT 1\]; 
           Assert.areEqual('ProductChangeOn'\+ event.ExternalId, audit.Name); 
           Assert.areEqual(5500, audit.Audit\_Price\_\_c); 
           Assert.areEqual('Coat', audit.Product\_Name\_\_c); 
    }
}