> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ditto.live/llms.txt
> Use this file to discover all available pages before exploring further.

# Testing

> Follow this guide to help you test changes you make to your Ditto integration code, data models, and business logic.

In addition to their production app in the Portal, most developers operate two additional apps: one for development and another for staging. A staging instance is set up as a pre-release sandbox that can simulate real-world environments and data.

## Ditto Server

Testing in a cloud environment offers scalability, flexibility, and cost
efficiency by allowing dynamic resource allocation and parallel testing. It
provides consistent, reproducible environments for reliable results and supports
advanced automated and performance testing capabilities.

Ditto Server isolates each app from one another by default in a multi-tenant
architecture, ensuring robust security and data privacy. This design allows
multiple tenants to share the same infrastructure while keeping their data and
applications completely separate.

The following approaches allow multiple developers to work on Ditto in parallel, without conflict.

* App per environment (dev, stage, prod), prefix collections with developer environment
  * Each developer can work within the same app
  * Running tests in isolation can be done by prefixing the collection with a unique identifier specific to that developer
  * For example, a Collection named `john_smith.orders.v3`
* App per developer
  * Each developer creates their own “app” within an organization. This creates a sandbox for a developer to isolate work and data from other developers
  * Starting a new test would require changing the Database ID on the Small Peer

### How do I migrate data between databases?

<Info>
  Please contact your dedicated support engineer to help migrate data between apps.
</Info>

**How to Reach Us:**

* **Ditto Portal:**
  * Log in to your account on the <a href="https://portal.ditto.live/" target="_blank">Ditto Portal</a>
  * The <a href="https://support.ditto.com" target="_blank">Support Portal</a> is located in the upper right hand side of the portal
* **Email:** Send an email to our support team at <a href="mailto:support@ditto.com" target="_blank">[support@ditto.com](mailto:support@ditto.com)</a>
  * Please include the details of the apps you wish to help migrate data between.

## Small Peer

To test Small Peer integration in isolation, we suggest using a wrapper library that includes an interface and mock implementation for unit testing. Ditto can be injected with an offline-only instance using an offline license token, and building a wrapper library includes an interface and a mock implementation for unit testing. This allows you to test small peer logic and syncing between small peers without relying on the availability of Ditto Server, which is great for testing within a CI/CD pipeline.

### Identity Switching

When testing the production readiness of your app, it is best practice to incorporate *dynamic identity switching* to debug potential issues related to roles, permissions, sync, and authentication workflows, such as cleanup and resource management when changing identities within your app.

In dynamic identity switching, end-user types adjust in realtime as a response to specific contexts or situations, without requiring an app restart or code change. From the end-user perspective, this automatic process means no interruptions or inconveniences like needing to log in again.

<Info>
  While testing with different digital identities is recommended during pre-production testing, this practice is *not* recommended for production environments due to potential performance and security concerns.
</Info>

To incorporate the process of automatically changing end-user types at runtime:

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    var ditto: Ditto? = nil
    ditto = Ditto(...)
    ```
  </Tab>

  <Tab title="Kotlin">
    ```Kotlin theme={null}
    var ditto: Ditto? = null
    ditto = Ditto(...)
    // or
    ditto?.close()
    ditto = Ditto(...)
    ```
  </Tab>

  <Tab title="JS">
    ```JS theme={null}
    let ditto = null;
    let ditto = new Ditto(...);
    // or
    ditto.close();
    let ditto = new Ditto(...);
    ```
  </Tab>

  <Tab title="Java">
    ```Java theme={null}
    Ditto ditto = null;
    ditto = new Ditto(...);
    // or
    ditto.close();
    ditto = new Ditto(...);
    ```
  </Tab>

  <Tab title="C#">
    ```C# theme={null}
    Ditto ditto = null;
    ditto = new Ditto(...);
    // or
    ditto.Close();
    ditto = new Ditto(...);
    ```
  </Tab>

  <Tab title="C++">
    ```cpp theme={null}
    Ditto* ditto = nullptr;
    ditto = new Ditto(...);
    // or
    delete ditto;
    ditto = new Ditto(...);
    ```
  </Tab>

  <Tab title="Rust">
    ```Rust theme={null}
    let mut ditto: Option<Ditto> = None;
    ditto = Some(Ditto::new(...));
    // or
    ditto = None;
    ditto = Some(Ditto::new(...));
    ```
  </Tab>

  <Tab title="Go">
    ```Go theme={null}
    var dit *ditto.Ditto
    dit, err := ditto.Open(...)
    // or
    dit.Close()
    dit, err = ditto.Open(...)
    ```
  </Tab>
</Tabs>

Ditto will persist data on each device. Data within the sandboxed application will be treated as new data and continue to sync, even if the developer changes the Database ID. We suggest changing the persistence directory to prepend the databaseId to the path to avoid this.

**Example Usage in iOS App**

For a real-world implementation of switching user identities in Swift, see the <a href="https://github.com/getditto/DittoSwiftTools/tree/f5938eb40a8fc3a3a73f87bb95745087903988b4/DittoToolsApp" target="_blank">DittoToolsApp</a> in the *getditto* > *DittoSwiftTools* repository on GitHub.

In this implementation, the <a href="https://github.com/getditto/DittoSwiftTools/blob/f5938eb40a8fc3a3a73f87bb95745087903988b4/DittoToolsApp/DittoToolsApp/DittoManager.swift#L51" target="_blank">`DittoManager`</a> method class configures, manages, and interacts with authentication functionality in the app.

## Simulating Offline and Disconnected Scenarios

When testing how your app behaves without a connection to Ditto Server, you have two approaches: blocking the connection at the network level, or disabling cloud sync programmatically via the transport configuration.

### Approach 1: Block Ditto Server at the Network Level

To simulate a cloud outage while keeping other internet access and peer-to-peer sync active, block connections to `*.cloud.ditto.live` using a firewall rule, DNS sinkhole, or proxy configuration on the test device or network.

<Warning>
  Your app must complete authentication and obtain a valid auth token **before** you block the connection. Ditto Small Peers require a valid token to operate — including for peer-to-peer sync. If you block `*.cloud.ditto.live` before the SDK authenticates, the device will not be able to obtain a token and sync will fail entirely.
</Warning>

<Steps>
  <Step title="Start the app and allow it to authenticate">
    Launch your app normally and confirm that the Ditto SDK has successfully authenticated and started sync. This ensures the device has a valid auth token cached locally.
  </Step>

  <Step title="Block connections to Ditto Server">
    Apply a firewall rule or DNS block for `*.cloud.ditto.live` on the test device or network. The device will lose its connection to Ditto Server but retain all other internet access.
  </Step>

  <Step title="Test your app's offline behavior">
    Exercise your app's functionality. Data reads, writes, and peer-to-peer sync with nearby devices should continue working normally. Verify that your app handles the absence of cloud sync gracefully.
  </Step>

  <Step title="Restore the connection">
    Remove the firewall rule or DNS block. The SDK will automatically reconnect to Ditto Server and sync any changes that were made while disconnected.
  </Step>
</Steps>

### Approach 2: Disable Cloud Sync via Transport Configuration

You can programmatically disable cloud sync by removing WebSocket URLs from the transport configuration. This keeps peer-to-peer transports active while preventing any connection to Ditto Server.

<CodeGroup>
  ```swift Swift theme={null}
  // Disable cloud sync while keeping P2P active
  ditto.updateTransportConfig { transportConfig in
    transportConfig.connect.webSocketURLs = []
  }
  ```

  ```kotlin Kotlin theme={null}
  // Disable cloud sync while keeping P2P active
  ditto.updateTransportConfig { transportConfig ->
    transportConfig.connect.webSocketURLs = mutableSetOf()
  }
  ```

  ```javascript JS theme={null}
  // Disable cloud sync while keeping P2P active
  ditto.updateTransportConfig((transportConfig) => {
    transportConfig.connect.webSocketURLs = [];
  });
  ```

  ```csharp C# theme={null}
  // Disable cloud sync while keeping P2P active
  ditto.UpdateTransportConfig(transportConfig =>
  {
    transportConfig.Connect.WebSocketURLs = new HashSet<string>();
  });
  ```

  ```cpp C++ theme={null}
  // Disable cloud sync while keeping P2P active
  ditto->update_transport_config([&](ditto::TransportConfig &transportConfig) {
    transportConfig.connect.websocket_urls = {};
  });
  ```

  ```rust Rust theme={null}
  // Disable cloud sync while keeping P2P active
  ditto.update_transport_config(|transport_config| {
    transport_config.connect.websocket_urls.clear();
  });
  ```
</CodeGroup>

<Info>
  Changing the transport configuration via `updateTransportConfig` takes effect immediately — you do not need to stop and restart sync. To re-enable cloud sync, add the WebSocket URL back to the configuration. See [Customizing Transport Configurations](/sdk/latest/sync/customizing-transport-configurations) for more details.
</Info>

## FAQ

<AccordionGroup>
  <Accordion title="Can I mock the Ditto server for CI use?">
    We don’t have anything to provide today. Stay tuned for Ditto Edge Server.
  </Accordion>

  <Accordion title="Can I run the Ditto Server on my local laptop?">
    We don’t have this yet, but it’s on the roadmap.
  </Accordion>

  <Accordion title="Is it a problem to have multiple apps?">
    No, it is designed for multi-tenancy.
  </Accordion>
</AccordionGroup>
