TGViewer
C# Short Posts 🔞 C# Short Posts 🔞 @dimasshortposts · 310 subscribers
Post #32 89
Как писать интеграционные тесты без InMemoryDB или SQLite?
Этот крутой вопрос поднял мой добрый коллега Паша Кириллин. И я в очередной раз убедился, насколько же я дуболом 🤖.

💩 Обычно, если я хочу написать тесты, которым зачем-то нужна реальная база, то я втупую напишу docker-compose.yaml с конфигурацией этой базы. И каждый раз при запуске дергаю docker compose up. В общем, довольно грубый метод.

А вот Паша посидел разок и задумался, а как бы это сделать автоматизированно, чтобы не пришлось делать docker compose up? И сразу нашел решение в виде такого репозитория: https://github.com/HofmeisterAn/dotnet-testcontainers

✅ Вы только посмотрите, как это работает:

using System.Threading.Tasks;
using DotNet.Testcontainers.Containers.Builders;
using DotNet.Testcontainers.Containers.Configurations.Databases;
using DotNet.Testcontainers.Containers.Modules.Abstractions;
using DotNet.Testcontainers.Containers.Modules.Databases;
using MySql.Data.MySqlClient;
using NUnit.Framework;

namespace TryTestContainers;

public sealed class UnitTest1
{
private readonly TestcontainerDatabase _testcontainers = new TestcontainersBuilder<MySqlTestcontainer>()
.WithDatabase(new MySqlTestcontainerConfiguration
{
Database = "db",
Username = "mysql",
Password = "mysql",
})
.Build();

[SetUp]
public async Task SetUp()
{
await _testcontainers.StartAsync();
}

[TearDown]
public async Task TearDown()
{
await _testcontainers.DisposeAsync().AsTask();
}

[Test]
public void TestMethod()
{
using MySqlConnection connection = new MySqlConnection(_testcontainers.ConnectionString);
using var command = new MySqlCommand();
connection.Open();
command.Connection = connection;
command.CommandText = "SELECT 1";
command.ExecuteReader();
}
}

Если вы, как и я, пропускаете большие блоки кода при чтении (да-да, ты не один такой ленивый, нас как минимум двое 👬), то вот вам текстовое описание происходящего:

1. В переменной _testcontainers мы создаем конфигурацию контейнера, также как мы это обычно делаем в docker-compose.yaml
2. В методе SetUp мы запускаем эти контейнеры. Они запускаются в вашем локальном Docker
3. В методе TestMethod мы подключаемся к базе данных и делаем запрос.
4. В методе TearDown мы их гасим, после всех тестов

Звучит достойно! Но еще более достойно звучит тот факт, что таким же макаром вы можете поднимать RabbitMq, Kafka и еще всякие штуки!

🅰️Итого: Если вам хочется делать тесты на уровне классов, которые ходят в инфраструктурные сервисы, вы можете использовать эту штуку. Но кажется надо посмотреть, как такие тесты поднимать в Github Actions? Как запускать их в параллель? Я попробую ответить на эти вопросы завтра, а вам пореомендую не сцать и тоже попробовать эту штуку!

P.S. Естественно, я въебал звезду на гитхабе этому проекту. И ты тоже не сиди, пойди и въеби звезду! У проекта уже 994 ⭐, так что это серьезно!
GitHub GitHub - testcontainers/testcontainers-dotnet: A library to support tests with throwaway instances of Docker containers for all… A library to support tests with throwaway instances of Docker containers for all compatible .NET Standard versions. - GitHub - testcontainers/testcontainers-dotnet: A library to support tests with ...
More from @dimasshortposts
  1. Oct 2, 2026s
  2. Oct 2, 2026Post #503
  3. Sep 30, 2026🛤 Путь до Tier1: от чего он зависит В прошлый раз мы гоняли hello world в цикле и увидели…
  4. Sep 26, 2026🧵 Тредик для вопросов по докладу про MAF на дотнексте В докладе многие подробности опусти…
  5. Sep 23, 2026Даже самым хардкорным ребятам надо отдыхать, так что отдыхаем, мои чюваки 🕺 🧑‍💻dp🥁 #he…
  6. Sep 16, 2026🎯 Instrumented Tier0: профилирование кода В прошлый раз мы разобрали два уровня компиляци…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →