{"id":14959462,"url":"https://github.com/dadrus/jpa-unit","last_synced_at":"2026-02-12T16:01:01.490Z","repository":{"id":57719686,"uuid":"52435170","full_name":"dadrus/jpa-unit","owner":"dadrus","description":"JUnit extension to test javax.persistence entities","archived":false,"fork":false,"pushed_at":"2019-12-02T11:54:19.000Z","size":1190,"stargazers_count":28,"open_issues_count":20,"forks_count":10,"subscribers_count":4,"default_branch":"master","last_synced_at":"2026-01-14T01:56:42.306Z","etag":null,"topics":["cdi","concordion","cucumber","database","java","jpa","jpa-test","jpa-unit","junit","junit5","mongodb","neo4j","persistence","test","testing"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dadrus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-02-24T10:47:32.000Z","updated_at":"2025-12-24T14:41:34.000Z","dependencies_parsed_at":"2022-09-26T21:40:56.323Z","dependency_job_id":null,"html_url":"https://github.com/dadrus/jpa-unit","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/dadrus/jpa-unit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dadrus%2Fjpa-unit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dadrus%2Fjpa-unit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dadrus%2Fjpa-unit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dadrus%2Fjpa-unit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dadrus","download_url":"https://codeload.github.com/dadrus/jpa-unit/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dadrus%2Fjpa-unit/sbom","scorecard":{"id":316609,"data":{"date":"2025-08-11","repo":{"name":"github.com/dadrus/jpa-unit","commit":"c59c9ba71d7aa6c58324cb288266881e2f0fe087"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.3,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 1/11 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 22 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":2,"reason":"8 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-5mg8-w23w-74h3","Warn: Project is vulnerable to: GHSA-7g45-4rm6-3mm3","Warn: Project is vulnerable to: GHSA-mvr2-9pj6-7w5j","Warn: Project is vulnerable to: GHSA-6pcc-3rfx-4gpm","Warn: Project is vulnerable to: GHSA-hwj3-m3p6-hj38","Warn: Project is vulnerable to: GHSA-8grg-q944-cch5","Warn: Project is vulnerable to: GHSA-j8jw-g6fq-mp7h","Warn: Project is vulnerable to: GHSA-j288-q9x7-2f5v"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-18T00:19:31.822Z","repository_id":57719686,"created_at":"2025-08-18T00:19:31.822Z","updated_at":"2025-08-18T00:19:31.822Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29371383,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-12T08:51:36.827Z","status":"ssl_error","status_checked_at":"2026-02-12T08:51:26.849Z","response_time":55,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cdi","concordion","cucumber","database","java","jpa","jpa-test","jpa-unit","junit","junit5","mongodb","neo4j","persistence","test","testing"],"created_at":"2024-09-24T13:19:47.349Z","updated_at":"2026-02-12T16:01:01.444Z","avatar_url":"https://github.com/dadrus.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/dadrus/jpa-unit.svg?branch=master)](https://travis-ci.org/dadrus/jpa-unit) \n[![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=com.github.dadrus.jpa-unit%3Ajpa-unit\u0026metric=alert_status)](https://sonarcloud.io/dashboard?id=com.github.dadrus.jpa-unit%3Ajpa-unit) \n[![Coverage Status](https://sonarcloud.io/api/project_badges/measure?project=com.github.dadrus.jpa-unit%3Ajpa-unit\u0026metric=coverage)](https://sonarcloud.io/dashboard?id=com.github.dadrus.jpa-unit%3Ajpa-unit) \n[![Technical Debt](https://sonarcloud.io/api/project_badges/measure?project=com.github.dadrus.jpa-unit%3Ajpa-unit\u0026metric=sqale_index)](https://sonarcloud.io/component_measures/?id=com.github.dadrus.jpa-unit%3Ajpa-unit) \n[![Maven Central](https://img.shields.io/maven-central/v/com.github.dadrus.jpa-unit/jpa-unit-core.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.github.dadrus.jpa-unit%22)\n\n# JPA Unit \n\nImplements [JUnit 4](http://junit.org/junit4) runner and rule, as well as [JUnit 5](http://junit.org/junit5) extension to enable easy testing of javax.persistence entities with an arbitrary persistence provider. Both JPA 2.0, as well as JPA 2.1 is supported (See [Issues](https://github.com/dadrus/jpa-unit/issues) for limitations).\n\n## Features\n\n- Makes use of standard `@PersistenceContext` and `@PersistenceUnit` annotations to inject the `EntityManager`, respectively `EntityManagerFactory`.\n- Solely relies on the JPA configuration (`persistence.xml`). No further JPA Unit specific configuration required. \n- Does not impose any JPA provider dependencies.\n- Implements automatic transaction management.\n- Enables JPA second level cache control \n- Offers different strategies to\n    - seed the database using predefined data sets (depending on the used data base - defined in XML, JSON, YAML or SQL statements)\n    - cleanup the database before or after the actual test execution based on data sets or arbitrary scripts\n    - execute arbitrary scripts before and/or after test execution\n    - verify contents of the database after test execution\n- Enables bootstrapping of the database schema and contents using plain data base statements (e.g. SQL) or arbitrary frameworks, like e.g. [FlywayDB](https://flywaydb.org) or [Liquibase](http://www.liquibase.org) before the starting of JPA provider\n- Implements seamless integration with CDI.\n- Supports acceptance based testing using [Cucumber](https://cucumber.io/docs/reference/jvm#java)\n- Supports acceptance based testing using [Concordion](http://concordion.org)\n- Supports SQL and NoSQL databases (based on what is possible with the chosen JPA provider). See below for a list of supported NoSQL databases and known limitations.\n\t\n## Credits\n\nThe implementation is inspired by the [Arquillian Persistence Extension](http://arquillian.org/modules/persistence-extension). Some of the code fragments are extracted out of it and adopted to suit the needs.\n\n# Maven Integraton\n\nTo be able to use the JPA Unit you will have to add some dependencies to your Maven project. For easier dependency management, there is a bom available which you can add to your `dependencyManagement` section:\n\n```xml\n\u003cdependencyManagement\u003e\n  \u003cdependency\u003e\n    \u003cgroupId\u003ecom.github.dadrus.jpa-unit\u003c/groupId\u003e\n    \u003cartifactId\u003ejpa-unit-bom\u003c/artifactId\u003e\n    \u003cversion\u003e${jpa-unit.version}\u003c/version\u003e\n    \u003ctype\u003epom\u003c/type\u003e\n    \u003cscope\u003eimport\u003c/scope\u003e\n  \u003c/dependency\u003e\n\u003c/dependencyManagement\u003e\n```\n\nThe actual dependencies are listed in sections addressing the different possible integration types.\n\n## JPA Unit with JUnit 4\n\nTo work with JUnit 4, you would need to add `jpa-unit4` to your test dependencies:\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.github.dadrus.jpa-unit\u003c/groupId\u003e\n  \u003cartifactId\u003ejpa-unit4\u003c/artifactId\u003e\n  \u003cversion\u003e${jpa-unit.version}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nThe basic requirements on the code level are the presence of either\n\n- the `@RunWith(JpaUnitRunner.class)` annotation on the class level, or\n- the `JpaUnitRule` property, annotated with `@Rule`\n\nExample using `JpaUnitRunner`:\n\n```java\n@RunWith(JpaUnitRunner.class)\npublic class MyTest {\n\n    @PersistenceContext(unitName = \"my-test-unit\")\n    private EntityManager manager;\n\t\n    @Test\n    public void someTest() {\n        // your code here\n    }\n}\n```\n\nExample using `JpaUnitRule`:\n\n```java\npublic class MyTest {\n\n    @Rule\n    public JpaUnitRule rule = new JpaUnitRule(getClass());\n\n    @PersistenceContext(unitName = \"my-test-unit\")\n    private EntityManager manager;\n\t\n    @Test\n    public void someTest() {\n        // your code here\n    }\n}\n```\n\n## JPA Unit with JUnit 5\n\nTo work with JUnit 5, you would need to add `jpa-unit5` to your test dependencies:\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.github.dadrus.jpa-unit\u003c/groupId\u003e\n  \u003cartifactId\u003ejpa-unit5\u003c/artifactId\u003e\n  \u003cversion\u003e${jpa-unit.version}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nOn the code level, there is no much choice for JUnit 5\n\n- the test class needs to be annotated with `@ExtendWith(JpaUnit.class)` annotation.\n\nExample:\n\n```java\n@ExtendWith(JpaUnit.class)\npublic class MyTest {\n\n    @PersistenceContext(unitName = \"my-test-unit\")\n    private EntityManager manager;\n\t\n    @Test\n    public void someTest() {\n        // your code here\n    }\n}\n```\n\n\n## Basic Configuration\n\nIrrespectively the JUnit version, the presence of either\n\n- an `EntityManager` property annotated with `@PersistenceContext`. In this case a new `EntityManager` instance is acquired for each test case. On test case exit it is cleared and closed. Furthermore the usage of an `EntityManager` instance managed by JPA Unit, enables automatic transaction management, where a new transaction is started before each test case and committed after the test case returns, respectively the method annotated with `@After`. The `@Transactional` annotation (see below) can be used to overwrite and configure the required behavior.\n- or an `EntityManagerFactory` property annotated with `@PersistenceUnit`. In this case the user is responsible for obtaining and closing the required `EntityManager` instance including the corresponding transaction management. There are however some utility functions which can ease the test implementation (see `TransactionSupport` class).\n\nis required. Irrespective of the used configuration, the `EntityManagerFactory` instance is acquired once and lives for the duration of the entire test suite implemented by the given test class.\n\nIn both cases the reference to the persistence unit is required as well (e.g. `@PersistenceContext(unitName = \"my-test-unit\")` or `@PersistenceUnit(unitName = \"my-test-unit\")`). Thus, given the presence of a persistence provider configuration, the examples, shown above, already implement full functional tests.\n\nLike in any JPA application, you have to define a `persistence.xml` file in the `META-INF` directory which includes the JPA provider and `persistence-unit` configuration. \nFor test purposes the `transaction-type` of the configured `persistence-unit` must be `RESOURCE_LOCAL`. \n\n## Property replacement\nIt is possible to configure `PersistenceProperties` within `@PersistenceContext` to override values in `persistence.xml`. In addition it is possible to use system properties to specify them from outside of the test.\nFor example: \n\n`-Dtest.jdbc.url=jdbc:oracle:thin:@myHost:1521:DB`\n\n```java\n@ExtendWith(JpaUnit.class)\npublic class MyTest {\n\n    @PersistenceContext(unitName = \"my-test-unit\", properties = {@PersistenceProperty(name = \"javax.persistence.jdbc.url\", value = \"${test.jdbc.url}\")})\n    private EntityManager manager;\n\t\n    @Test\n    public void someTest() {\n        // your code here\n    }\n}\n```\n\n# Control the Behavior\n\nTo control the test behavior, JPA Unit comes with a handful of annotations and some utility classes. All these annotations can be applied on class and method level, where the latter always takes precedence over the former.\nJPA Unit follows the concept of configuration by exception whenever possible. To support this concept its API consists mainly of annotations with meaningful defaults (if the annotation is not present) used to drive the test. \n\n- `@ApplyScriptsBefore`, which can be used to define arbitrary scripts which shall be executed before running the test method.\n- `@ApplyScriptsAfter`, which can be used to define arbitrary scripts which shall be executed after running the test method.\n- `@Bootstrapping`, which can be used to define a method executed only once before the bootstrapping of a JPA provider happens. This can be handy e.g. to setup a test specific DB schema. \n- `@Cleanup`, which can be used to define when the database cleanup should be triggered.\n- `@CleanupCache`, which can be used to define whether and when the JPA L2 cache should be evicted.\n- `@CleanupUsingScripts`, which can be used to define arbitrary scripts which shall be used for cleaning the database.\n- `@ExpectedDataSets`, which provides the ability to verify the state of underlying database using data sets. Verification is invoked after test's execution.\n- `@InitialDataSets`, which provides the ability to seed the database using data sets before test method execution.\n- `@Transactional`, which can be used to control the automatic transaction management for a test if supported by the chosen JPA provider for the chosen database. Otherwise it does not have any effect.\n- `TransactionSupport`, comes in handy when fine grained transaction management is required or automatic transaction management is disabled. As for the `@Transactional` annotation, if not supported by the chosen JPA provider for the chosen database, the usage of these functions has no effect.\n\nAll these elements are described in more detail below.\n\n## Transactional Tests\n\nLike already written above automatic transaction management is active if the test uses an `EntityManager` instance controlled by JPA Unit. To tweak the required behavior you can use the `@Transactional` annotation either on a test class to apply the same behavior for all tests, or on a single test. This annotation has following properties:\n\n- `value` of type `TransactionMode`. Following modes are available:\n    - `COMMIT`. The test is wrapped in a transaction which is committed on return. This is the **default** behavior.\n    - `DISABLED`. The transactional support is disabled.\n    - `ROLLBACK`. Perform a _rollback_ on test return.\n    \nExample which disables transactional support for all tests implemented by a given class:\n\n```java\n@RunWith(JpaUnitRunner.class)\n@Transactional(TransactionMode.DISABLED)\npublic class MyTest {\n\n    @PersistenceContext(unitName = \"my-test-unit\")\n    private EntityManager manager;\n\t\n    @Test\n    public void someTest() {\n        // your code here\n    }\n}\n```\n    \n`TransactionSupport` becomes handy, when fine graned transaction management is desired or automatic transaction management is disabled (e.g. the test injects `EntityManagerFactory`). Following methods are available:\n\n- `newTransaction(EntityManager em)` is a static factory method to create new `TransactionSupport` object\n- `flushContextOnCommit(boolean flag)` can be used to configure the `TransactionSupport` object to *flush* the `EntityManager` after the transaction is committed.\n- `clearContextOnCommit(boolean flag)` can be used to configure the `TransactionSupport` object to *clear* the `EntityManager` after the transaction is committed.\n- `execute(\u003cExpression\u003e)` executes the given expression and wraps it in a new transaction. If the expression returns a result, it is returned to the caller. Following behavior is implemented:\n    - Before the execution of `\u003cExpression\u003e`: If an active transaction is already running, it is committed and a new transaction is started. Otherwise just a new transaction is started.\n    - After the execution of `\u003cExpression\u003e`: The transaction wrapping the `\u003cExpression\u003e` is committed. If an active transaction was running and was committed before the `\u003cExpression\u003e` wrapping transaction was started, a new transaction is started. \n\nHere a usage example:\n\n```java\n@RunWith(JpaUnitRunner.class)\n@Transactional(TransactionMode.DISABLED)\npublic class MyTest {\n\n    @PersistenceContext(unitName = \"my-test-unit\")\n    private EntityManager manager;\n\n    @Test\n    public void someTest() {\n        newTransaction(manager).execute(() -\u003e {\n            // some code wrapped in a transaction\n        });\n\n    int result = newTransaction(manager)\n        .clearContextOnCommit(true)\n        .execute(() -\u003e {\n            // some code wrapped in a transaction\n            return 1;\n        });\n    }\n}\n```\n\n## Seeding the Database\n\nCreating ad-hoc object graphs in a test to seed the database can be a complex task on the one hand and made the test less readable. On the other hand it is usually not the goal of a test case, rather a prerequisite. \nTo address this, JPA Unit provides an alternative way in a form of database fixtures, which are easy configurable and can be applied for all tests or for a single test. To achieve this JPA Unit uses the concept of data sets.\nIn essence, data sets are files containing data to be inserted into the database. Since data sets are database specific, see the corresponding database specific sections for details on supported types and formats.\n\nTo seed the database using data set files put the `@InitialDataSets` annotation either on the test itself or on the test class. This annotation has following properties:\n\n- `value` of type `String[]` which takes a list of data set files used to seed the database.\n- `seedStrategy` of type `DataSeedStrategy` which can be used to defined the seeding strategy. Following strategies are available:\n    - `CLEAN_INSERT`. Performs insert of the data defined in provided data sets, after removal of all data present in the tables referred in provided files.\n    - `INSERT`. Performs insert of the data defined in provided data sets. This is the **default** strategy.\n    - `REFRESH`. During this operation existing rows are updated and new ones are inserted. Entries already existing in the database which are not defined in the provided data set are not affected.\n    - `UPDATE`. This strategy updates existing rows using data provided in the data sets. If data set contain a row which is not present in the database (identified by its primary key) then exception is thrown.\n\nUsage example:\n\n```java\n@RunWith(JpaUnitRunner.class)\n@InitialDataSets(\"datasets/initial-data.json\")\npublic class MyTest {\n\n    @PersistenceContext(unitName = \"my-test-unit\")\n    private EntityManager manager;\n\t\n    @Test\n    public void someTest() {\n        // your code here\n    }\n}\n```\n\n## Running Custom Catabase Scripts\n\nSeeding the database as described above introduces an additional abstraction level, which is not always desired on one hand. On other hand, there might be a need to disable specific database constraint checks before a database cleanup might be performed (latter only possible in a post test execution step). Usage of plain scripts (e.g. SQL) comes in handy here to execute any action directly on the database level. Simply put `@ApplyScriptBefore` and/or `@ApplyScriptAfter` annotation on your test class and/or directly on your test method. Corresponding scripts will be executed before and/or after test method accordingly. If there is definition on both, test method level annotation takes precedence.\n\nBoth annotation have the following properties:\n\n- `value` of type `String[]` which needs to be set to reference the required database specific scripts (e.g. SQL for a relational database).\n    \nUsage example:\n\n```java\n@RunWith(JpaUnitRunner.class)\n@ApplyScriptBefore(\"scrips/some-script.script\")\npublic class MyTest {\n\n    @PersistenceContext(unitName = \"my-test-unit\")\n    private EntityManager manager;\n\t\n    @Test\n    @ApplyScriptAfter({\n        \"scrips/some-other-script-1.script\",\n        \"scrips/some-other-script-2.script\"\n    })\n    public void someTest() {\n        // your code here\n    }\n}\n```\n\n## Database Content Verification\n\nAsserting database state directly from testing code might imply a huge amount of work. `@ExpectedDataSets` comes in handy here. Just put this annotation either on a test class to apply the same assertions for all tests, or on a single test method (the latter takes precedence) and JPA Unit will use the referenced files to check whether the database contains entries you are expecting after the test execution. \n\nThe `@ExpectedDataSets` annotation has the following properties:\n\n- `value` of type `String[]` which takes a list of data set files used for post-test verification of the database's state.\n- `orderBy` of type `String[]` which takes a list of columns to be used for sorting rows to determine the order of data sets comparison (Not supported by all database types).\n- `excludeColumns` of type `String[]` which takes a list of columns to be excluded during the comparison.\n- `filter` of type `Class\u003c?\u003e[]` which takes a list of custom filters to be applied during verification in the specified order (Not supported by all database types)\n- `strict` of type `boolean` which defines whether the performed verification about expected data sets is strict or not. In strict mode all tables/collections and entries not defined in the expected data sets are considered to be an error. This is the **default** strategy.\n\nBoth `orderBy` and `excludeColumns` properties can be used to define columns with and without dotted notation. With dotted notation one can explicitly define the table/collection in addition to the actual field/property (see also the example below).\n\nUsage example:\n\n```java\n@RunWith(JpaUnitRunner.class)\npublic class MyTest {\n\n    @PersistenceContext(unitName = \"my-test-unit\")\n    private EntityManager manager;\n\t\n    private Depositor depositor;\n\n    @Before\n    public void createTestData() throws OperationNotSupportedException {\n        depositor = new Depositor(\"Max\", \"Doe\");\n        depositor.addContactDetail(new ContactDetail(ContactType.EMAIL, \"john.doe@acme.com\"));\n        depositor.addContactDetail(new ContactDetail(ContactType.TELEPHONE, \"+1 22 2222 2222\"));\n        depositor.addContactDetail(new ContactDetail(ContactType.MOBILE, \"+1 11 1111 1111\"));\n        final InstantAccessAccount instantAccessAccount = new InstantAccessAccount(depositor);\n        final GiroAccount giroAccount = new GiroAccount(depositor);\n        giroAccount.setCreditLimit(1000.0f);\n        giroAccount.deposit(100.0f);\n        giroAccount.transfer(150.0f, instantAccessAccount);\n    }\n\n    @Test\n    @ExpectedDataSets(value = \"datasets/expected-data.json\", excludeColumns = {\n            \"ID\", \"DEPOSITOR_ID\", \"ACCOUNT_ID\", \"VERSION\"\n    }, orderBy = {\n            \"CONTACT_DETAIL.TYPE\", \"ACCOUNT_ENTRY.TYPE\"\n    })\n    public void test1() {\n        manager.persist(depositor);\n    }\n}\n```\n\n## Cleaning the Database\n\n### Strategy based Cleanup\n\nBy default the database content is entirely erased before each test. If you want to control this behavior, `@Cleanup` annotation is your friend. It defines when database cleanup should be triggered and which cleanup strategy to apply. \nAs always, you can use this annotation globally on a class level or on a method level. The latter takes precedence.\n\nThe `@Cleanup` annotation has the following properties:\n\n- `strategy` of type `CleanupStrategy`. Defines which strategy to apply while erasing the database content. Following strategies are available:\n    - `STRICT`. Cleans entire database. This is the **default** strategy. Might require turning off database constraints (e.g. referential integrity).\n    - `USED_ROWS_ONLY`. Deletes only those entries which were defined in data sets.\n    - `USED_TABLES_ONLY`. Deletes only those tables/collections which were used in data sets.\n- `phase` of type `CleanupPhase`. Defines the phase when the database cleanup should be triggered. Following phases are available:\n    - `BEFORE`. The contents of database are deleted (based on the strategy) before the test method is executed.\n    - `AFTER`. The contents of database are deleted (based on the strategy) after the test method is executed. This is the **default** phase.\n    - `NONE`. The cleanup of the database is disabled.\n    \n\nUsage example:\n\n```java\n@RunWith(JpaUnitRunner.class)\n@Cleanup(TransactionMode.BEFORE) // change the default phase from AFTER to BEFORE\npublic class MyTest {\n\n    @PersistenceContext(unitName = \"my-test-unit\")\n    private EntityManager manager;\n\t\n    @Test\n    public void someTest() {\n        // your code here\n    }\n    \n    @Test\n    @Cleanup(phase = CleanupPhase.AFTER, strategy = CleanupStrategy.USED_ROWS_ONLY)\n    public void otherTest() {\n        // your code here\n    }\n}\n```\n\n### Using Custom Scripts\n\nIf automatic cleanup as described in [Strategy based Cleanup](#strategy-based-cleanup) does not suit your needs, `@CleanupUsingScripts` might be your friend. You can use it to execute custom scripts to clean your database before or after the test. Just put this annotation either on the test itself or on the test class. As always the definition applied on the test method level takes precedence.\n\nThis annotation has following properties:\n\n- `value` of type `String[]` which needs to be set to reference the required database specific cleanup scripts.\n- `phase` of type `CleanupPhase`. Defines the phase when the cleanup scripts should be executed. Following phases are available:\n    - `BEFORE`. Before the test method is executed.\n    - `AFTER`. After the test method is executed. This is the **default** phase.\n    - `NONE`. The execution of scripts is disabled.\n    \nUsage example:\n\n```java\n@RunWith(JpaUnitRunner.class)\npublic class MyTest {\n\n    @PersistenceContext(unitName = \"my-test-unit\")\n    private EntityManager manager;\n    \n    @Test\n    @CleanupUsingScripts(phase = CleanupPhase.AFTER, value = \"scripts/delete-all.script\")\n    public void otherTest() {\n        // your code here\n    }\n}\n```\n\n## Controlling Second Level Cache\n\nThe JPA L2 cache can be a two-edged sword if configured or used improperly. Therefore it is crucial to test the corresponding behavior as early as possible. JPA Unit enables this by the usage of the `@CleanupCache` annotation either on a test class, to apply the same behavior for all tests, or on a single test level to define whether and when the JPA L2 cache should be evicted . Please note: The behavior of the second level can be configured in the `persistence.xml`. If `@CleanupCache` is used and the defined `phase` (see below) is not `NONE`, the second level cache will be evicted regardless the settings defined in the `persistence.xml`. This annotation has following properties:\n\n- `phase` of type `CleanupPhase`. Defines the phase when the second level cache cleanup should be triggered. Following phases are available:\n    - `BEFORE`. The L2 cache is evicted before the test method is executed.\n    - `AFTER`. The L2 cache is evicted after the test method is executed. This is the **default** phase.\n    - `NONE`. The eviction of the L2 cache is disabled.\n    \nExample which evicts the JPA L2 cache before the execution of each test method implemented by a given class:\n\n```java\n@RunWith(JpaUnitRunner.class)\n@CleanupCache(TransactionMode.BEFORE)\npublic class MyTest {\n\n    @PersistenceContext(unitName = \"my-test-unit\")\n    private EntityManager manager;\n\t\n    @Test\n    public void someTest() {\n        // your code here\n    }\n}\n```\n\n## Bootstrapping of DB Schema \u0026 Contents\n\nBootstrapping of the data base schema, as well as the handling of its evolution over a period of time is a crucial topic. To enable a data base schema \u0026 contents setup close to the productive environment in which the JPA provider usually relies on this given DB setup, the corresponding database specific actions need to be done before the JPA provider is loaded by accessing the data base directly. JPA Unit enables this by the usage of the `@Bootstrapping` annotation. A dedicated method of a test class, which implements a data base scheme \u0026 contents setup can be annotated with this annotation and is required to have one parameter of type `DataSource`. JPA Unit will execute this method very early in its bootstrapping process. Because of this neither `EntityManager` nor `EntityManagerFactory` cannot be used at this time.\n\nFor tests, which use this feature, the JPA provider should be configured not to drop and create the data base schema on start, rather to verify it. For e.g. Hibernate this can be achieved by setting the `hibernate.hbm2ddl.auto` property to the value `validate`.\n\nUsage example (bootstrapping with FlywayDB):\n\n```.java\n@RunWith(JpaUnitRunner.class)\npublic class FlywaydbTest {\n\n    @PersistenceContext(unitName = \"my-verification-unit\")\n    private EntityManager manager;\n\n    @Bootstrapping\n    public void prepareDataBase(final DataSource ds) {\n        // creates db schema and puts some data\n        final Flyway flyway = new Flyway();\n        flyway.setDataSource(ds);\n        flyway.clean();\n        flyway.migrate();\n    }\n\n    @Test\n    public void someTest() {\n        // your test specific code here\n    }\n}\n```\n\n# Supported Databases\n\nDepending on the used database, you will have to add a dependency for a database specific JPA-Unit plugin.\n\n## RDBMS Databases\n\nFor all relational databases the `jpa-unit-rdbms` dependency needs to be added:\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.github.dadrus.jpa-unit\u003c/groupId\u003e\n  \u003cartifactId\u003ejpa-unit-rdbms\u003c/artifactId\u003e\n  \u003cversion\u003e${jpa-unit.version}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nHere JPA Unit makes use of the standard \n- `javax.persistence.jdbc.driver`,\n- `javax.persistence.jdbc.url`,\n- `javax.persistence.jdbc.user` and\n- `javax.persistence.jdbc.password`\n\nThe last two are optional (depending on the requirements of the underlying database).\n\nproperties to access the database directly.\n\nHere an example of a `persistence.xml` file which configures [EclipseLink](http://www.eclipse.org/eclipselink) and [H2](http://www.h2database.com/html/main.html) database:\n\n```xml\n\u003cpersistence version=\"2.1\"\n  xmlns=\"http://xmlns.jcp.org/xml/ns/persistence\" \n  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n  xsi:schemaLocation=\"http://xmlns.jcp.org/xml/ns/persistence \n    http://www.oracle.com/webfolder/technetwork/jsc/xml/ns/persistence/persistence_2_1.xsd\"\u003e\n\t\n  \u003cpersistence-unit name=\"my-test-unit\" transaction-type=\"RESOURCE_LOCAL\"\u003e\n    \u003cprovider\u003eorg.eclipse.persistence.jpa.PersistenceProvider\u003c/provider\u003e\n\n    \u003c!-- your classes converters, etc --\u003e\n\n    \u003cproperties\u003e\n      \u003cproperty name=\"eclipselink.ddl-generation\" value=\"drop-and-create-tables\" /\u003e\n      \u003cproperty name=\"eclipselink.target-database\" \n          value=\"org.eclipse.persistence.platform.database.H2Platform\" /\u003e\n      \u003cproperty name=\"javax.persistence.jdbc.driver\" value=\"org.h2.Driver\" /\u003e\n      \u003cproperty name=\"javax.persistence.jdbc.url\" \n          value=\"jdbc:h2:mem:serviceEnablerDB;DB_CLOSE_DELAY=-1\" /\u003e\n      \u003cproperty name=\"javax.persistence.jdbc.user\" value=\"test\" /\u003e\n      \u003cproperty name=\"javax.persistence.jdbc.password\" value=\"test\" /\u003e\n    \u003c/properties\u003e\n  \u003c/persistence-unit\u003e\n\u003c/persistence\u003e\n```\n\n### Data Set Format\n\nThanks to [DBUnit](http://dbunit.sourceforge.net/), which is used internally for all RDBMS, following data set formats are supported:\n\n- XML (Flat XML Data Set). A simple XML structure, where each element represents a single row in a given table and attribute names correspond to the table columns as illustrated below.\n- YAML. Similar to the flat XML layout, but has some improvements (columns are calculated by parsing the entire data set, not just the first row)\n- JSON. Similar to YAML.\n- XSL(X). With this data set format each sheet represents a table. The first row of a sheet defines the columns names and remaining rows contains the data.\n- [CSV](https://www.ietf.org/rfc/rfc4180.txt). Here a data set can be constructed from a directory containing csv files, each representing a separate table with its entries.\n\n\nHere some data set examples:\n\n```xml\n\u003cdataset\u003e\n\t\u003cDEPOSITOR id=\"100\" version=\"1\" name=\"John\" surname=\"Doe\" /\u003e\n\t\u003cADDRESS id=\"100\" city=\"SomeCity\" country=\"SomeCountry\" street=\"SomeStreet 1\" \n\t         zip_code=\"12345\" owner_id=\"100\"/\u003e\n\t\u003cADDRESS id=\"101\" city=\"SomeOtherCity\" country=\"SomeOtherCountry\" street=\"SomeStreet 2\" \n\t         zip_code=\"54321\" owner_id=\"100\"/\u003e\n\u003cdataset\u003e\n```\n\n```yaml\nDEPOSITOR:\n  - id: 100\n    version: 1\n    name: John\n    surname: Doe\n\nADDRESS:\n  - id: 100\n    city: SomeCity\n    country: SomeCountry\n    street: SomeStreet 1\n    zip_code: 12345\n    owner_id: 100\n  - id: 101\n    city: SomeOtherCity\n    country: SomeOtherCountry\n    street: SomeStreet 2\n    zip_code: 54321\n    owner_id: 100\n```\n\n```json\n\"DEPOSITOR\": [\n\t{ \"id\": \"100\", \"version\": \"1\", \"name\": \"John\", \"surname\": \"Doe\" }\n],\n\"ADDRESS\": [\n\t{ \"id\":\"100\", \"city\":\"SomeCity\", \"country\": \"SomeCountry\", \"street\": \"SomeStreet 1\", \n\t  \"zip_code\": \"12345\", \"owner_id\": \"100\" },\n\t{ \"id\":\"101\", \"city\":\"SomeOtherCity\", \"country\": \"SomeOtherCountry\", \"street\": \"SomeStreet 2\", \n\t  \"zip_code\": \"54321\", \"owner_id\": \"100\" }\n]\n```\n\n### DBUnit specific configuration\n\nAll [DBUnit specific settings](http://dbunit.sourceforge.net/properties.html) can be configured by just making a `dbunit.properties` file available in the classpath. Long and short property names are supported.\n\nPlease note, that JPA-Unit configures the required DBUnit `datatypeFactory` and `metadataHandler` automatically based on the used JDBC driver.\n\n\n## MongoDB\n\nFor [MongoDB](https://www.mongodb.com), the `jpa-unit-mongodb` dependency needs to be added:\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.github.dadrus.jpa-unit\u003c/groupId\u003e\n  \u003cartifactId\u003ejpa-unit-mongodb\u003c/artifactId\u003e\n  \u003cversion\u003e${jpa-unit.version}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nJPA Unit needs to connect to a running MongoDB instance. This is done using [mongo-java-driver](https://mongodb.github.io/mongo-java-driver/). Usage of an in-process, in-memory MongoDB implementations, like [Fongo](https://github.com/fakemongo/fongo) is not possible.\nTo overcome this limitation, or made it at least less painful, one can use e.g.\n\n- [Flapdoodle Embedded MongoDB](https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo) for the lifecycle management of a MongoDB instance from code, e.g. from `@BeforeClass` and `@AfterClass` annotated methods. You can find working example within the JPA Unit integration test project for MongoDB. \n- [embedmongo-maven-plugin](https://github.com/joelittlejohn/embedmongo-maven-plugin) for the lifecycle management of a MongoDB instance through Maven.\n\n### Supported JPA Provider\n\nSince JPA does not address NoSQL databases, each JPA provider defines its own properties. These properties are also the only dependencies to a specific JPA provider implementation. As of todays JPA Unit MongoDB extension can use the properties of the following JPA provider:\n\n- [Hibernate OGM (with MongoDB extension)](https://docs.jboss.org/hibernate/ogm/5.2/reference/en-US/html_single/#ogm-mongodb).\n- [EclipseLink (with MongoDB extension)](https://www.eclipse.org/eclipselink/documentation/2.6/concepts/nosql002.htm)\n- [DataNucleus (with MongoDB extension)](http://www.datanucleus.org/products/datanucleus/jpa/samples/tutorial_mongodb.html)\n- [Kundera (with MongoDB extension)](https://github.com/impetus-opensource/Kundera/wiki/Kundera-with-MongoDB)\n\n### Data Set Format\n\nDefault data set format for MongoDB is _JSON_. In a simple case it must comply with the following example structure:\n\n```.json\n{\n  \"collection_name_1\": [\n    {\n      \"property_1\": \"value_1\",\n      \"property_2\": \"value_2\"\n    },\n    {\n      \"property_3\": NumberLong(10),\n      \"property_4\": { \"$date\": \"2017-06-07T15:19:10.460Z\" }\n    }\n  ],\n  \n  \"collection_name_2\": [\n    {\n      \"property_5\": 4,\n      \"property_7\": \"value_7\"\n    }\n  ]\n}\n```\n\nIf indexes (for more information on MongoDB indexes and types see [MongoDB Indexes](https://docs.mongodb.com/manual/indexes/)) need to be included as well, the following structure applies:\n\n```.json\n{\n  \"collection_name_1\": {\n    \"indexes\": [\n      {\n        \"index\": {\n          \"property_1\": 1\n        },\n        \"index\": {\n          \"property_2\": 1,\n          \"options\": {\n            \"unique\": true,\n            \"default_language\": \"english\"\n          }\n        }\n      },\n      {\n        \"index\": {\n          \"property_3\": 1,\n          \"property_4\": -1\n        }\n      }\n    ],\n    \"data\": [\n      {\n        \"property_1\": \"value_1\",\n        \"property_2\": \"value_2\"\n      },\n      {\n        \"property_3\": NumberLong(10),\n        \"property_4\": { \"$date\": \"2017-06-07T15:19:10.460Z\" }\n      }\n    ]\n  }\n}\n``` \n\nPlease note, that in this case the collection document consists of two subdocuments. The first one - `indexes` is where the indexes are defined. Basically this is which fields of the collection are going to be indexed.\nThe second one - `data`, where all documents, which belong to the collection under test, are defined. In both cases all the types defined by MongoDB are supported.\n\n## Neo4j\n\nFor [Neo4j](https://www.neo4j.com), the `jpa-unit-neo4j` dependency needs to be added:\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.github.dadrus.jpa-unit\u003c/groupId\u003e\n  \u003cartifactId\u003ejpa-unit-neo4j\u003c/artifactId\u003e\n  \u003cversion\u003e${jpa-unit.version}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nJPA Unit needs to connect to a running Neo4j instance. This is done using [Neo4j JDBC Driver](http://neo4j-contrib.github.io/neo4j-jdbc/), which as a neat side effect makes bootstrapping \n(see [Bootstrapping of DB Schema \u0026 Contents](#bootstrapping-of-db-schema--contents)) of the DB possible e.g. using [LIQUIGRAPH](http://www.liquigraph.org/). Usage of an in-process, \nin-memory Neo4j implementation is only possible if the embedded data base is configured to expose BOLT or HTTP interfaces. This can be achieved by the use of e.g.\n\n- [Neo4J Harness](https://neo4j.com/docs/java-reference/current/) for the lifecycle management of a Neo4j instance from code, e.g. for test purposes by using a `Neo4jRule`. You can find working example as part of integration tests of JPA-Unit's neo4j project.\n\n### Supported JPA Provider\n\nSince JPA does not address NoSQL databases, each JPA provider defines its own properties. These properties are also the only dependencies to a specific JPA provider implementation. As of todays JPA Unit Node4j\nextension can use the properties of the following JPA provider:\n\n- [Hibernate OGM (with Neo4j extension)](https://docs.jboss.org/hibernate/ogm/5.2/reference/en-US/html_single/#ogm-neo4j).\n- [DataNucleus (with Neo4j extension)](http://www.datanucleus.org/products/datanucleus/jpa/samples/tutorial_neo4j.html)\n- [Kundera (with Neo4j extension)](https://github.com/impetus-opensource/Kundera/wiki/Neo4J-Specific-Configuration)\n\nEven the last two support Neo4j in an embedded mode only, both can be used if the embedded Neo4j database exposes HTTP or BOLT interfaces (like available with Neo4j Harness). Since there is no possibility to define the corresponding\ninterfaces (BOLT or HTTP) in a standard way (by the means of the regular `persistence.xml`), JPA-Unit makes use of a `jpa-unit.properties` file, which has to be made available on the class path and which has to define the following\nproperties:\n\n- `connection.url`, which defines the url to the available interface. E.g. `jdbc:neo4j:bolt://localhost:7687`. This property is mandatory.\n- `user.name`, which defines the user name to be used during connection establishment. This property is optional.\n- `user.password`, which defines the password of the user to be used during connection establishment. This property is optional as well.\n\nSame approach can be used if Hibernate OGM Neo4j extension is used in embedded mode.\n\n**A special note on Kundera:** It still depends on a pretty old Neo4j (1.8.1) version. So even JPA-Unit's neo4j extension understands the configuration dialect of Kundera, I didn't find a version of Noe4j Harness, which can expose BOLT or \nHTTP protocols and is binary compatible with the version used by Kundera. With other words, as long as Kundera is not updated to use a more recent version of Neo4j, the usage of this JPA provider will most probably be not possible. \n\n### Data Set Format\n\nThanks to [jgrapht](https://github.com/jgrapht/jgrapht), which is used internally for graph handling, following data set formats are supported:\n\n- [GraphML](http://graphml.graphdrawing.org/primer/graphml-primer.html). an XML-based file format for graphs.\n\nIf you want to generate/export data out of an existing Neo4j instance [APOC](https://neo4j-contrib.github.io/neo4j-apoc-procedures/) can be really helpful.\nBe however aware, that the data exported by APOC does not fully comply with GraphML. APOC generated file does not include `key` elements definitions for\n`label` and `labels` `data` elements for `edge`, respectively `node` elements. It also adds additional attributes (`label` and `labels`) to `node` and `edge`\nelements which are not defined by GraphML. The first one needs to be addressed by adding the missing `\u003ckey id=\"labels\" for=\"node\" attr.name=\"labels\" attr.type=\"string\"/\u003e`\nand `\u003ckey id=\"label\" for=\"edge\" attr.name=\"label\" attr.type=\"string\"/\u003e` to the `graph` element. The second one can be ignored - schema compliance is not enforced by\nJPA-Unit's neo4j extension.\n\nHere's an example:\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\"?\u003e\n\u003cgraphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" \n  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n  xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\"\u003e\n  \u003ckey id=\"name\" for=\"node\" attr.name=\"name\" attr.type=\"string\"/\u003e\n  \u003ckey id=\"id\" for=\"node\" attr.name=\"id\" attr.type=\"long\"/\u003e\n  \u003ckey id=\"labels\" for=\"node\" attr.name=\"labels\" attr.type=\"string\"/\u003e\n  \u003ckey id=\"label\" for=\"edge\" attr.name=\"label\" attr.type=\"string\"/\u003e\n  \u003cgraph id=\"G\" edgedefault=\"directed\"\u003e\n    \u003cnode id=\"1\" labels=\":Person\"\u003e\n      \u003cdata key=\"labels\"\u003e:Person\u003c/data\u003e\n      \u003cdata key=\"name\"\u003eTom\u003c/data\u003e\n      \u003cdata key=\"id\"\u003e1\u003c/data\u003e\n    \u003c/node\u003e\n    \u003cnode id=\"2\" labels=\":Person\"\u003e\n      \u003cdata key=\"labels\"\u003e:Person\u003c/data\u003e\n      \u003cdata key=\"name\"\u003eJerry\u003c/data\u003e\n      \u003cdata key=\"id\"\u003e2\u003c/data\u003e\n    \u003c/node\u003e\n    \u003cedge id=\"3\" source=\"1\" target=\"2\" label=\"friend\"\u003e\n      \u003cdata key=\"label\"\u003efriend\u003c/data\u003e\n    \u003c/edge\u003e\n  \u003c/graph\u003e\n\u003c/graphml\u003e\n```\n\n# CDI Integration\n\nTo be able to use the JPA Unit with CDI, all you need in addition to your CDI test dependency, like [DeltaSpike Test-Control Module](https://deltaspike.apache.org/documentation/test-control.html) or [Gunnar's CDI Test](https://github.com/guhilling/cdi-test), is to add the following dependency to your Maven project :\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.github.dadrus.jpa-unit\u003c/groupId\u003e\n  \u003cartifactId\u003ejpa-unit-cdi\u003c/artifactId\u003e\n  \u003cversion\u003e${jpa-unit.version}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nThis dependency implements a CDI extension, which proxies the configured `EntityManager` producer. During a JPA Unit test run it uses the `EntityManager` configured in the test class instance. In all other cases it just uses the proxied producer.\n\nUsage example:\n\n```.java\n@RunWith(CdiTestRunner.class)\npublic class CdiEnabledJpaUnitTest {\n\n    @Rule\n    public JpaUnitRule rule = new JpaUnitRule(getClass());\n\n    @PersistenceContext(unitName = \"my-test-unit\")\n    private static EntityManager manager;\n\n    @Inject\n    private SomeRepository repo;\n\n    @Test\n    public void someTest() {\n        // use CDI managed objects, like the repo from above\n    }\n}\n```\n\n# Cucumber Integration\n\nCucumber is a BDD test framework. To be able to use JPA Unit with it, all you need in addition to cucumber dependencies is to add the following dependency to your Maven project :\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.github.dadrus.jpa-unit\u003c/groupId\u003e\n  \u003cartifactId\u003ejpa-unit-cucumber\u003c/artifactId\u003e\n  \u003cversion\u003e${jpa-unit.version}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nThis dependency implements a Cucumber extension (`ObjectFactory`) which intercepts all cucumber feature glue methods to enable the usage of JPA Unit annotations. \n\nSince each feature/scenario glue, compared to regular JUnit tests, implements a single test specification, JPA Unit disables automatic data base cleanup. To avoid stale data\nbetween the executions of different scenarios or more general different tests, you should take care of the cleanup by yourself. This is the only difference to the regular behavior. \nThis cleanup can be achieved, e.g. using the `@Cleanup` annotation on e.g. a method annotated with the cucumber `@After` annotation.\n\nAnalogue to regular JUnit tests a cucumber glue needs to reference either an `EntityManager` or an `EntityManagerFactory`. The `EntityManagerFactory` lives for the\nduration of the scenario execution.\n\nSame rules as for regular JUnit tests apply for the `EntityManager` as well: An `EntityManager` for `TRANSACTION` `PersistenceContextType` lives only for the duration\nof the execution of the glue method. An `EntityManager` for `EXTENDED` `PersistenceContextType` has the life time of the `EntityManagerFactory` and is closed after the\nlast glue method is executed. Latter configuration might be a better choice for cucumber glue.\n\nUsage example:\n\n```.java\n@RunWith(Cucumber.class)\npublic class CucumberTest {\n    // According to cucumber, this class should not implement any tests\n}\n```\n\n```.java\npublic class CucumberGlue {\n\n    @Rule\n    public JpaUnitRule rule = new JpaUnitRule(getClass());\n\n    @PersistenceContext(unitName = \"my-test-unit\", type = PersistenceContextType.EXTENDED)\n    private EntityManager manager;\n  \n    @Given(\"^an some existing data in the db$\")\n    @InitialDataSets(\"datasets/initial-data.json\")\n    public void seedDatabase() {\n        // data base is seeded thanks to the jpa unit annotation\n    }\n  \n    @When(\"^a new object is inserted$\")\n    public void updataData() {\n        // e.g. manager.persist(new SomeEntity());\n    }\n  \n    @Then(\"^it is expected in the db\")\n    @ExpectedDataSets(value = \"datasets/expected-data.json\")\n    public void verifyData() {\n        // db verification is done thanks to the jpa unit annotation\n    }\n  \n    @After\n    @Cleanup\n    public void cleanupDb() {\n        // to avoid stale data\n    } \n}\n```\n\nIf you would like to use cucumber with JPA Unit and CDI, you will have to follow the requirements from [CDI Integration](#cdi-integration). However, since\nthe usage of multiple runners is not possible, you'll have to start the CDI container manually. Here an example with Deltaspike:\n\n```.java\n@RunWith(Cucumber.class)\npublic class CucumberTest {\n    // According to cucumber, this class should not implement any tests\n    // but we can implement global setup and tear down functionality here.\n  \n    private static CdiContainer cdiContainer;\n\n    @BeforeClass\n    public static void startContainer() {\n        cdiContainer = CdiContainerLoader.getCdiContainer();\n        cdiContainer.boot();\n    }\n\n    @AfterClass\n    public static void stopContainer() {\n        cdiContainer.shutdown();\n    }\n}\n```\n\nNow you can inject your dependencies into glue objects.\n\n# Concordion Integration\n\nConcordion is a BDD test framework. To be able to use JPA Unit with it, all you need in addition to concordion dependencies is to add the following dependency to your Maven project :\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.github.dadrus.jpa-unit\u003c/groupId\u003e\n  \u003cartifactId\u003ejpa-unit-concordion\u003c/artifactId\u003e\n  \u003cversion\u003e${jpa-unit.version}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nThis dependency implements a specialized `ConcordionRunner` - the `JpaUnitConcordionRunner` which you have to use with the JUnit `@RunWith` annotation on the class level. \nThis runner hooks into concordion implementation and intercepts all fixture methods referenced from corresponding specifications, thus enables the usage of JPA Unit annotations\non fixture methods. \n\nSince each fixture/specification(-example), compared to a regular JUnit tests, implements a single test specification, JPA Unit disables automatic data base cleanup. To avoid stale data\nbetween the executions of different scenarios or more general different tests, you should take care of the cleanup by yourself. This is the only difference to the regular behavior. \nThis cleanup can be achieved, e.g. using the `@Cleanup` annotation on e.g. a method annotated with the concordion `@AfterSpecification` annotation.\n\nAnalogue to regular JUnit tests a concordion fixture needs to reference either an `EntityManager` or an `EntityManagerFactory`. The `EntityManagerFactory` lives for the\nduration of the scenario execution.\n\nSame rules as for regular JUnit tests apply for the `EntityManager` as well: An `EntityManager` for `TRANSACTION` `PersistenceContextType` lives only for the duration\nof the execution of the fixture method. An `EntityManager` for `EXTENDED` `PersistenceContextType` has the life time of the `EntityManagerFactory` and is closed after the\nlast fixture method is executed. Latter configuration might be a better choice for concordion fixtures.\n\nUsage example:\n\n```.java\n@RunWith(JpaUnitConcordionRunner.class)\npublic class ConcordionFixture {\n    \n    @PersistenceContext(unitName = \"my-test-unit\", type = PersistenceContextType.EXTENDED)\n    private EntityManager manager;\n    \n    public Depositor createNewCustomer(final String customerName) {\n        final String[] nameParts = customerName.split(\" \");\n        final Depositor depositor = new Depositor(nameParts[0], nameParts[1]);\n        new InstantAccessAccount(depositor);\n        return depositor;\n    }\n\n    public void finalizeOnboarding(final Depositor depositor) {\n        manager.persist(depositor);\n    }\n\n    @ExpectedDataSets(value = \"datasets/max-payne-data.json\", excludeColumns = {\n            \"ID\", \"DEPOSITOR_ID\", \"ACCOUNT_ID\", \"VERSION\", \"accounts\"\n    })\n    @Cleanup(phase = CleanupPhase.AFTER)\n    public void verifyExistenceOfExpectedObjects() {\n        // The check is done via @ExpectedDataSets annotation\n    }\n}\n```\n\nThe associated specification looks like this:\n```.markdown\n# Create New Depositor\n\nDuring the on-boarding of a new banking customer for an instant access account a new depositor as well\nas a new instant access account have to be created. \n \n\n### [Example](- \"Onboard a new customer\")\n\nGiven a new customer *[Max Payne](- \"#customer = createNewCustomer(#TEXT)\")*, applying for an instant\naccess account\n\nWhen the [onboarding process completes](- \"finalizeOnboarding(#customer)\")\n\nThen a new depositor object and a new instant access account object are \n[present in the system](- \"verifyExistenceOfExpectedObjects()\").\n```\n\nIf you would like to use concordion with JPA Unit and CDI, you will have to follow the requirements from [CDI Integration](#cdi-integration). However, since\nthe usage of multiple runners is not possible, you'll have to start the CDI container manually. Here's an excerpt demonstrating CDI usage:\n\n```.java\n@RunWith(JpaUnitConcordionRunner.class)\npublic class ConcordionFixture {\n    private static CdiContainer cdiContainer;\n\n    @BeforeSpecification\n    public static void startContainer() {\n        cdiContainer = CdiContainerLoader.getCdiContainer();\n        cdiContainer.boot();\n    }\n\n    @AfterSpecification\n    public static void stopContainer() {\n        cdiContainer.shutdown();\n    }\n    \n    // ...\n}\n```\n\nNow you can inject your dependencies into the fixture class.\n\nIf you organize your fixtures/specifications in a hierarchical story, it will make more sense to start and stop the CDI container in the root fixture\nusing methods annotated with `@BeforeSuite`, respectively `@AfterSuite`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdadrus%2Fjpa-unit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdadrus%2Fjpa-unit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdadrus%2Fjpa-unit/lists"}