You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Experimental package that provides a simple TestContainer setup for XUnit v3 test assemblies. See the [test containers documentation](docs/TestContainers/README.md) for more details.
For database support you can use `Fusonic.Extensions.UnitTests.EntityFrameworkCore`, optionally with specific support for PostgreSQL in `Fusonic.Extensions.UnitTests.EntityFrameworkCore.Npgsql`.
115
+
For database support you can use `Fusonic.Extensions.UnitTests.EntityFrameworkCore`, optionally with specific support for
116
+
- PostgreSQL in `Fusonic.Extensions.UnitTests.EntityFrameworkCore.Npgsql`
117
+
- SQL Server in `Fusonic.Extensions.UnitTests.EntityFrameworkCore.SqlServer`
116
118
117
119
The basic idea behind those is that every test gets its own database copy. This enables parallel database testing and avoids any issues from tests affecting other tests.
118
120
@@ -153,22 +155,15 @@ public class TestFixture : ServiceProviderTestFixture
The interface of `ITestStore` is straight forward. You can easily replace your test store with something else for another strategy or for supporting other databases.
169
-
170
166
When using `IDbContextFactory`, the factory must be registered with scoped lifetime, not with the default singleton lifetime.
When using the `NpgsqlDatabasePerTest` it is assumed that you use a prepared database template. This template should have all migrations applied and may contain some seeded data. Each test gets a copy of this template. With the `PostgreSqlUtil`, we provide an easy way to create such a template.
179
174
180
-
You can either create a small console application that creates the template, or do it directly once in the fixture during setup.
181
-
182
-
#### PostgreSQL template option: Create it in the fixture
175
+
You can either create a small console application that creates the template, or do it directly once in the test startup.
183
176
184
-
You can create the template directly in the TestFixture by specifying a `TemplateCreator` in the options:
177
+
A simple way to create that template is provided in `PostgreSqlUtil`. Example:
By default, if the template creator is set, the `TestStore` checks exactly once, if the database exists.
203
-
- If the template database exists, no action will be taken. It is not checked, if the database is up to date.
204
-
- If the template database does not exist, the `TemplateCreator` is executed.
205
-
- All future calls won't do anything and just return.
206
-
207
-
`PostgreSqlUtil.CreateTestDbTemplate` force drops and recreates your database. However, it won't be called if the datbase already exists.
183
+
By default this only creates the template, if the database does not exist yet. This speeds up testing in local development when running tests multiple times. You can change this behaviour to always create a fresh template by setting the parameter `overwrite` to `true`.
208
184
209
-
In order to get updates to your test database, either drop it or restart your postgresql container, if its data partition is mounted to `tmpfs`.
185
+
### PostgreSQL - TestContainers
210
186
211
-
You can change this behavior to always create a template by setting `options.AlwaysCreateTemplate`to true. In that case, the `TemplateCreator` will always be executed once per test run. This will increase the startup time for your test run though.
187
+
To get your test PostgreSQL server up and running, a simple solution is to use [TestContainers](https://testcontainers.com/) and start one during test startup. This ensures that the test configuration in your local development and in your CI pipelines is the same.
Alternatively, if you prefer to create the test database externally before the test run, create a console application with the following code in `Program.cs`:
With that, the database given in the connection string is getting force dropped, recreated, migrations applied and optionally seeded via the given `TestDataSeed`. You can simply call it in your console or the build pipeline before running the tests using
229
-
```sh
230
-
dotnet run --project <pathToCsProject>"<connectionString>"
231
-
```
189
+
For an example how we use TestContainers see [UnitTests.EntityFrameworkCore.Npgsql.Tests.TestStartup](../../src/UnitTests.EntityFrameworkCore.Npgsql/test/TestStartup.cs) and [TestFixture](../../src/UnitTests.EntityFrameworkCore.Npgsql/test/TestFixture.cs)
232
190
233
191
### Microsoft SQL Server - Configure DbContext
234
192
235
-
A `TestStore` is used for handling the test databases. For Microsoft SQL Server, you can use the `SqlServerDatabasePerTestStore`, which creates a separate database for each test. You have to pass the connection string to the database and a method to create the test database. Register it as follows:
193
+
A `TestStore` is used for handling the test databases. For Microsoft SQL Server, you can use the `SqlServerDatabasePerTestStore`, which creates a separate database for each test. You just have to pass it the connection string to the template and register it as follows:
vartestStore=newSqlServerDatabasePerTestStore(Configuration.GetConnectionString("SqlServer")); // or TestStartup.ConnectionString when using TestContainers
The connection string must have the `Intial catalog` set. It determines the name of the template database. All tests will use a copy of the template database.
260
209
261
-
The `TemplateCreator` specifies the method to create a template. It has to create and seed the database and create a backup for the copies used for the tests. Fortunately, the `SqlServerTestUtil` provides a method to do exactly that.
262
-
263
210
When using `IDbContextFactory`, the factory must be registered with scoped lifetime, not with the default singleton lifetime.
To get your test SQL Server server up and running, a simple solution is to use [TestContainers](https://testcontainers.com/) and start one during test startup. This ensures that the test configuration in your local development and in your CI pipelines is the same.
218
+
219
+
For an example how we use TestContainers see [UnitTests.EntityFrameworkCore.SqlServer.Tests.TestStartup](../../src/UnitTests.EntityFrameworkCore.SqlServer/test/TestStartup.cs) and [TestFixture](../../src/UnitTests.EntityFrameworkCore.SqlServer/test/TestFixture.cs)
220
+
269
221
### Configuring any other database
270
222
271
223
The database support is not limited to PostgreSql and SQL Server. You just have to implement and register the `ITestStore`.
272
224
273
-
For a simple example with SqLite, check `Fusonic.Extensions.UnitTests.EntityFrameworkCore.Tests` -> `SqliteTestStore`and `TestFixture`.
225
+
For a simple example with SqLite, check [UnitTests.EntityFrameworkCore.Tests.SqliteTestStore](../../src/UnitTests.EntityFrameworkCore/test/SqliteTestStore.cs)and [TestFixture](../../src/UnitTests.EntityFrameworkCore/test/TestFixture.cs).
274
226
275
227
### Support mulitple databases in a test
276
228
@@ -281,74 +233,38 @@ public class TestFixture : ServiceProviderTestFixture
XUnit limits the number the maximum _active_ tests executing, but it does not the limit of maximum parallel tests.
318
-
Simplified, as soon as a test awaits a task somewhere, the thread is returned to the pool and another test gets started. This is intended by design.
250
+
## Running in GitLab
319
251
320
-
This behavior can cause issues when running integration tests against a database, especially when lots of tests are started. Connection limits can be exhausted quickly.
252
+
In order to use TestContainers in GitLab, start `docker:dind-rootless` as a service. When running rootless dind, you also must set `TESTCONTAINERS_RYUK_DISABLED` to `true`, as there is no `docker.sock` available. Ryuk is responsible for cleaning up the test containers, even when test jobs get cancelled. Disabling it should be safe though, as the containers started within `docker:dind` get cleaned up anyway after the job ends.
321
253
322
-
To solve this, you can either throttle your tests, or increase the max. connections of your test database.
323
-
324
-
To increase the max. connections of your postgres test instance, just pass the parameter max_connections. Example for a docker compose file:
254
+
Example:
325
255
```yaml
326
-
postgres_test:
327
-
image: postgres:17
328
-
command: -c max_connections=500
329
-
ports:
330
-
- "5433:5432"
331
-
volumes:
332
-
- type: tmpfs
333
-
target: /var/lib/postgresql/data
334
-
- type: tmpfs
335
-
target: /dev/shm
336
-
environment:
337
-
POSTGRES_PASSWORD: developer
338
-
```
339
-
340
-
Alternatively, if you want to throttle your tests instead, you can to this easily with a semaphore in your test base:
0 commit comments