Testing A Connector Locally
If you want to validate the code of a connector locally, you need to have a data object and at least one Cache Writer or one Action Processor implemented and know the API you are building the connector for.
At this point
- You understand what a connector is.
- You have implemented the API Client and related files.
- You have a data object and at least one Cache Writer or Action Processor implemented
To test the connector locally, the CLI and connector project offers some useful functionality. You can verify if the connector works by: 1. Initializing a test-settings.json file 2. Configuring test-settings.json in your root "Connector" folder 3. Configuring launchSettings.json in the "Properties" folder 4. Using your development environment or command line to run
Instructions
Run Test Init Command
Always build your project before running xchange test init
to keep the file up to date. This creates a file named test-settings.json and populates it scaffolding based on your current connecter setup. Like most commands, make sure to execute it in the "Connector" directory where Connector.csproj is located.
Command
xchange test init
Warning
Always build the project before the command is run. Must execute the command in the directory where the csproj file of the connector is. If you don’t you will get an error message like the following:
xchange test init
Error Time: 11:42:29.299 Could not find a CSPROJ file in the directory: /Users/builder/Documents/svc/trimble/connector-product
Expected Results on Success
xchange test init
Information Time: 11:44:41.110 /Users/builder/Documents/svc/trimble/connector-product/Connector/test-settings.json could not be found. Creating a new file.
Information Time: 11:44:41.191 Test data generated in /Users/builder/Documents/svc/trimble/connector-product/Connector/test-settings.json
Enter Configuration In the Test Settings file
Test-settings.json contains several different sections which will need to be configured, including connectorRegistration, activeConnection, connections, serviceConfiguration, and data. By default it is listed in gitignore and you will need to enter credentials here to test your api such as username, password, bearer token, etc. as appropriate for your authorization setup.
{
"testSettings": {
"connectorRegistration": { … }, // api configuration
"activeConnection": "apiKeyAuth", // definition key of connection to use
"connections": [ // predefined connections to test against
{ … },
{ … },
],
"app-1": { // module to test
"serviceConfiguration": { … } // configuration of the module
"data": { … } // test data objects
}
}
}
connectorRegistrations
The connectorRegistration
section coordinates with what you have under the Connector/ConnectorRegistrationConfig.cs - This is where you enter test data - on the App Xchange platform these fields would be completed by the user. It might include a Username, Password, Company or Account ID, or a wide variety of things depending on the specific API and product the Connector is for.
{
"connectorRegistration": {
"companyId": 123,
"startDate": "08-04-1989",
"userName": "myTestUserNameHere",
"password": "myTestPasswordHere",
"accountId": "myTestAccountIdHere"
},
}
activeConnection
Define the connection you want to use for your test. Enter the definitionKey
of the connection you want to test with.
{
"activeConnection": "apiKeyAuth",
}
connections - currently only applies if using --auth-type
An array of credentials that you want to test against. Only one will be used per test run.
{
"connections": [
{
"definitionKey": "apiKeyAuth",
"configuration": {
"apiKey": "super-user",
"connectionEnvironment": 1
}
},
{
"definitionKey": "basicAuth",
"configuration": {
"username": "normal-user",
"password": "123456",
"connectionEnvironment": 1
}
},
…,
],
…
}
Module ID section (app-1 default example)
Contains the serviceConfiguration
and data
keys for each module to test. The serviceConfiguration
section contains information about what Action Processors and Cache Writers exist for the connector, and which ones to test. Set "UploadObject" to "true" to run and "false" to ignore/skip. The data
section contains information on the data objects broken down by event and type.
{
"app-1": {
"serviceConfiguration": {
"actionProcessor": {
"AddHealthCheckConfig": {
"ProcessQueuedEvent": true,
"TestAPIFailure": false,
"TestCacheSyncFailure": false
},
},
"cacheWriter": {
"HealthCheckConfig": {
"UploadObject": true,
"ValidateCacheInsert": false,
"ValidateCacheUpdate": false,
"ValidateCacheDelete": false
}
}
}
},
"data": {
"health-check": {
"add": [
{
"Timestamp": "2024-06-25T22:50:19.9781118Z"
}
]
}
}
}
Full Example of a test-settings.json
- Non connection configuration needed for interacting with the external system API.
- Which connection to use
- List of available connections
- Flag to enable the CreateEmployees action when the Action Processor Local Development profile runs.
- Flag to enable the cache writer of the Employees data object when the Cache Writer Local Development profile runs.
- All the CreateEmployeesActionInput properties that are used to test the CreateEmployees action.
- All the UpdateEmployeesActionInput properties that are used to test the UpdateEmployees action.
{
"testSettings": {
"connectorRegistration": {
"apiDetails": { // (1)
"cuisine": "",
"type": "",
"diet": "",
}
},
"activeConnection": "basicAuth", // (2)
"connections": [ // (3)
{
"definitionKey": "apiKeyAuth",
"configuration": {
"apiKey": "",
"connectionEnvironment": 1
}
},
{
"definitionKey": "basicAuth",
"configuration": {
"username": "",
"password": "",
"connectionEnvironment": 1
}
}
],
"app-1": {
"serviceConfiguration": {
"actionProcessor": {
"AddHealthCheckConfig": {
"ProcessQueuedEvent": true,
"TestAPIFailure": false,
"TestCacheSyncFailure": false
},
"CreateEmployeesConfig": {
"ProcessQueuedEvent": true // (4)
},
"UpdateEmployeesConfig": {
"ProcessQueuedEvent": true
},
"DeleteEmployeesConfig": {
"ProcessQueuedEvent": true
}
},
"cacheWriter": {
"HealthCheckConfig": {
"UploadObject": true,
"ValidateCacheInsert": false,
"ValidateCacheUpdate": false,
"ValidateCacheDelete": false
},
"EmployeesConfig": {
"UploadObject": true // (5)
}
}
},
"data": {
"health-check": {
"add": [
{
"Timestamp": "2024-06-25T22:50:19.9781118Z"
}
]
},
"employees": {
"create": [ // (6)
{
"firstName": "",
"lastName": "",
"phone": "",
"email": "",
"address": "",
"city": "",
"state": "",
"zip": ""
}
],
"update": [ // (7)
{
"employeeId": 0,
"firstName": "",
"lastName": "",
"phone": "",
"email": "",
"address": "",
"city": "",
"state": "",
"zip": ""
}
],
"delete": [
{
"employeeId": 0
}
]
}
}
}
}
}
Run Test Locally
Now that you've configured test-settings.jon, locate Connector/Properties/launchSettings.json. This file contains information about the launch profile, such as the application URL and the environment variables.
What does the launchSettings File Contain and what is its purpose:
The launchSettings.json is a configuration file used in C# projects. It defines various settings related to the application's launch, such as environment variables, command-line arguments, and debugging settings. This file is located within the "Properties" folder of your project and is used by the development environment to determine how the application should run.
In the launchSettings file locate the sections
Action Processor Local Development
Cache Writer Local Development
Testing Cache Writer
Command
dotnet run --launch-profile "Cache Writer Local Development"
This or any profile can be run via the IDE of your choosing as well. Feel free to use which one you are comfortable with.
Example Expected Results on Success
$ dotnet run --launch-profile "Cache Writer Local Development"
Local development is currently configured. You'll need to use the Xchange.Connector.SDK.Test.Local library
<6>ESR.Hosting.RunService[0] ESR (1.0.6.0) Host started in 0.646475 seconds
<6>ESR.Hosting.RunService[0] Running job 60ab563e-06be-491b-ac91-78b0d668288e for Subscriber Id 0
Time to Retrieve Service Run Message and Signal Started: 966
Time to initialize context: 68
Time to validate context: 94
[12:17:28 INF] Writing <fieldwire/app/1/project> (Asynchronous) data objects to cache
[12:17:29 INF] Change detection system determined that there were 10 new records, 0 updated records, 0 unchanged records, and 0 deleted records for object of type <fieldwire/app/1/project>.
[12:17:29 INF] App Network sync summary for fieldwire/app/1/project
Inserts: 10 successful, 0 no change, 0 failed
Updates: 0 successful, 0 no change, 0 failed
Deletes: 0 successful, 0 no change, 0 failed
Time to Finish Service: 752
<6>ESR.Hosting.RunService[0] Service runner shutting down…
Note
When you run the cache writer or action processor a directory named ‘databases’ gets created as well as a file under that directory named local-test-what-goes-here.db
.
The path of that file is here Connector/databases/local-test-what-goes-here.db
.
On a local test cache write, the connector talks to the API pulls down the information, and stores it on a local database file.
Testing Action Processor
- Go to Properties/launchSettings.json
- Locate the section
Action Processor Local Development
- Under the field/property
commandLineArgs
- Fill out the
--dataObjectUrl XXXX --actionUrl XXXX
part of the command line for data object and action - note it is case sensitive based on the CLI command.
Example
--dataObject project --action create
Command
dotnet run --launch-profile "Action Processor Local Development"
Expected Results on Success
Local development is currently configured. You'll need to use the Xchange.Connector.SDK.Test.Local library
<6>ESR.Hosting.RunService[0] ESR (1.0.6.0) Host started in 0.42326 seconds
<6>ESR.Hosting.RunService[0] Running job 35b583fe-ffb8-4090-bfd9-98a335313a19 for Subscriber Id 0
Time to Retrieve Service Run Message and Signal Started: 928
Time to initialize context: 76
Time to validate context: 89
[12:24:53 INF] Starting action processor for any queued actions
[12:24:54 INF] Action with ID ffd85a7f-335a-4c38-8cfb-d182c974e0c2 closed as Failed
[12:24:54 INF] Processing actions complete. 1 were handled. 0 queued actions were skipped
Time to Finish Service: 424
<6>ESR.Hosting.RunService[0] Service runner shutting down...
Expected Error If Data Object or Action Command Line Argument Are Wrong
dotnet run --launch-profile "Action Processor Local Development"
Local development is currently configured. You'll need to use the Xchange.Connector.SDK.Test.Local library
<6>ESR.Hosting.RunService[0] ESR (1.0.6.0) Host started in 0.503598 seconds
<6>ESR.Hosting.RunService[0] Running job fc746eda-9a10-49a4-b3ac-9e565be8ecf3 for Subscriber Id 0
Time to Retrieve Service Run Message and Signal Started: 1016
Time to initialize context: 76
Time to validate context: 84
[12:24:38 INF] Starting action processor for any queued actions
[12:24:38 ERR] An error occurred during action processing
System.Exception: Unable to resolve an IAction<> type for the module 'app-1' and the DataObject 'project' and its action 'Create'
at Xchange.Connector.SDK.Test.Local.TestDataSource.GetIActionInterface()
at Xchange.Connector.SDK.Test.Local.TestDataSource.GetTestQueuedData()
at Xchange.Connector.SDK.Test.Local.Client.LocalAppNetworkClient.GetQueuedActions(String urlPart, String actionPath, CancellationToken cancellationToken)
at ESR.Hosting.Action.ActionHandlerService.HandleActionsInActionQueueAsync()
<3>ESR.Hosting.RunService[0] Exception while running service System.Exception: Unable to resolve an IAction<> type for the module 'app-1' and the DataObject 'project' and its action 'Create' at Xchange.Connector.SDK.Test.Local.TestDataSource.GetIActionInterface() at Xchange.Connector.SDK.Test.Local.TestDataSource.GetTestQueuedData() at Xchange.Connector.SDK.Test.Local.Client.LocalAppNetworkClient.GetQueuedActions(String urlPart, String actionPath, CancellationToken cancellationToken) at ESR.Hosting.Action.ActionHandlerService.HandleActionsInActionQueueAsync() at Xchange.Connector.SDK.Hosting.ServiceRunner.RunServiceAsync(IConnectorServiceDefinition serviceDefinition, CancellationToken cancellationToken) at Xchange.Connector.SDK.Hosting.ServiceRunner.RunAsync(CancellationToken cancellationToken) at ESR.Hosting.RunService.StartAsync(CancellationToken cancellationToken)
<6>ESR.Hosting.RunService[0] Service runner shutting down...
Resetting Local Cache
If you need to reset the local databases (Change detection and cache) this command will do so:
Command
xchange test reset
Summary
At this point, you should have used the test init command to prepopulate a test-settings.json file and configured it for testing, and run the test according to launchSettings.json with your IDE or command line. You can repeat the build->test init->configure->launch process as you complete your connector.