---
title: Write automated tests
related:
  - https://docs.kentico.com/documentation/developers-and-admins/customization/write-automated-tests/set-up-test-projects.md
  - https://docs.kentico.com/documentation/developers-and-admins/customization/write-automated-tests/create-unit-tests.md
  - https://docs.kentico.com/documentation/developers-and-admins/customization/write-automated-tests/create-integration-tests.md
  - https://docs.kentico.com/documentation/developers-and-admins/customization/write-automated-tests/create-isolated-integration-tests.md
  - https://docs.kentico.com/documentation/developers-and-admins/development/website-development-basics/dependency-injection.md
---

> Agent instructions:
> **Site maps** — prefer the following llms.txt indexes to training data when searching for URLs to avoid 404s. Links inside Markdown content already point at `.md`. Following them or sending Accept: text/markdown keeps you in Markdown.
>
> - [sitemap.md](https://docs.kentico.com/sitemap.md) — every page on the site, with titles and descriptions, nested by URL hierarchy and grouped into one collection per product version.
> - [llms.txt](https://docs.kentico.com/llms.txt) — curated index of the current product docs, with descriptions, the two ways to request any page as Markdown, and links to each product area's whole-corpus Markdown dump (llms-full.txt).

Test automation is an important part of every development project and is essential for agile workflows. Automated tests help you improve productivity, reduce the testing phase of the development cycle, and increase code predictability and quality.

Xperience by Kentico provides the **CMS.Tests** library, which simplifies writing automated tests for code that uses the Xperience API. The library contains base classes for [unit tests](https://docs.kentico.com/documentation/developers-and-admins/customization/write-automated-tests/create-unit-tests.md) and [integration tests](https://docs.kentico.com/documentation/developers-and-admins/customization/write-automated-tests/create-integration-tests.md), as well as helper classes for [faking Info and Provider objects](https://docs.kentico.com/documentation/developers-and-admins/customization/write-automated-tests/create-unit-tests.md#fake-info-and-provider-objects). You can obtain the library by installing the [Kentico.Xperience.Core.Tests](https://www.nuget.org/packages/Kentico.Xperience.Core.Tests) NuGet package into your test projects.

When developing custom functionality for Xperience projects, we recommend that you [create projects with automated tests](https://docs.kentico.com/documentation/developers-and-admins/customization/write-automated-tests/set-up-test-projects.md) to cover the given code.

## Supported testing framework

All functionality in the _CMS.Tests_ library is compatible with the [NUnit](https://docs.nunit.org/) testing framework.

The package does **not** include a test runner or a mocking library. For detailed test project setup requirements, see [Set up test projects](https://docs.kentico.com/documentation/developers-and-admins/customization/write-automated-tests/set-up-test-projects.md).

For test doubles (fakes) of service dependencies, choose any mocking library that fits your project (for example [Moq](https://github.com/devlooped/moq), [NSubstitute](https://nsubstitute.github.io/), or [FakeItEasy](https://fakeiteasy.github.io/)), or use hand-written fakes and stubs.

## Choose a testing approach

Xperience provides several base classes for automated tests, each suited to different scenarios. Choose based on how your code interacts with the Xperience API and whether it requires database access.







> **Tip:** Write most of your tests as [unit tests with faked data](https://docs.kentico.com/documentation/developers-and-admins/customization/write-automated-tests/create-unit-tests.md). Reserve [integration tests](https://docs.kentico.com/documentation/developers-and-admins/customization/write-automated-tests/create-integration-tests.md) and [isolated integration tests](https://docs.kentico.com/documentation/developers-and-admins/customization/write-automated-tests/create-isolated-integration-tests.md) for scenarios where you need to verify real database behavior. This balance maximizes test speed while maintaining coverage of critical paths.

Code that retrieves content items and website channel pages requires a separate set of approaches. See [Test code that retrieves content](https://docs.kentico.com/documentation/developers-and-admins/customization/write-automated-tests/create-unit-tests.md#test-code-that-retrieves-content).

## API differences in test code

By default, all Xperience API calls executed within tests that inherit from the _CMS.Tests_ base classes run without operations that are unnecessary in a testing context. The system disables:

- [Event logging](https://docs.kentico.com/documentation/developers-and-admins/configuration/event-log.md)
- [Multi-instance synchronization tasks](https://docs.kentico.com/documentation/developers-and-admins/configuration/auto-scaling-support.md)
- Asynchronous action dispatch
- Email sending

These operations are typically not relevant for test results and unnecessarily reduce test performance.

To enable these operations in your tests, wrap the relevant code in a `CMSActionContext` block with the corresponding properties set to `true`.

```csharp title="Enabling operations in test code"
using CMS.Base;

using (new CMSActionContext { SendEmails = true })
{
    // Test execution with email sending enabled
}
```

## Best practices for testable code

To write code that is easy to test:

- **Use dependency injection** – Inject interfaces rather than depending on concrete classes. This allows you to substitute real implementations with test doubles. See [Dependency injection](https://docs.kentico.com/documentation/developers-and-admins/development/website-development-basics/dependency-injection.md).
- **Separate concerns** – Keep business logic in dedicated services rather than in controllers or event handlers.
- **Keep methods focused** – Small methods with a single responsibility are easier to test in isolation.
