Skip to content

Commit

Permalink
Document support for @MicronautTest transactional and rollback (#249)
Browse files Browse the repository at this point in the history
* Add JUnit documentation for transactional and rollback

* Add test for rollback = false in Spock

* Add Spock documentation for transactional and rollback

* Add Kotest / Kotlintest documentation for transactional and rollback

* Refactoring docs to avoid copy/paste
  • Loading branch information
alvarosanchez authored Aug 21, 2020
1 parent bbac585 commit 8ac3daf
Show file tree
Hide file tree
Showing 10 changed files with 156 additions and 114 deletions.
19 changes: 19 additions & 0 deletions src/main/docs/guide/includes/environments-classpath-scanning.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
The `@MicronautTest` annotation supports specifying the environment names the test should run with:

```java
@MicronautTest(environments=["foo", "bar"])
```

In addition, although Micronaut itself doesn't scan the classpath, some integrations do (such as JPA and GORM), for these cases you may wish to specify either the application class:

```java
@MicronautTest(application=Application.class)
```

Or the packages:

```java
@MicronautTest(packages="foo.bar")
```

To ensure that entities can be found during classpath scanning.
8 changes: 8 additions & 0 deletions src/main/docs/guide/includes/refreshing-requires.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
You can use combine the use of `@Requires` and `@Property`, so that injected beans will be refreshed if there are
configuration changes that affect their `@Requires` condition.

For that to work, the test must be annotated with `@MicronautTest(rebuildContext = true)`. In that case, if there are
changes in any property for a given test, the application context will be rebuilt so that `@Requires` conditions are
re-evaluated again.

For example:
16 changes: 16 additions & 0 deletions src/main/docs/guide/includes/transaction.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
By default, if `org.springframework:spring-tx` is in the test classpath (eg transitively via
`io.micronaut.configuration:micronaut-hibernate-jpa-spring`), when using `@MicronautTest`, each `@Test` method will be
wrapped in a transaction that will be rolled back when the test finishes. This behaviour can be changed by using the
`transactional` and `rollback` properties.

To avoid creating a transaction:

```java
@MicronautTest(transactional = false)
```

To not rollback the transaction:

```java
@MicronautTest(rollback = false)
```
30 changes: 4 additions & 26 deletions src/main/docs/guide/junit5.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -92,26 +92,11 @@ include::{junit5tests}/MathServiceTest.java[]

=== Environments, Classpath Scanning etc.

The `@MicronautTest` annotation supports specifying the environment names the test should run with:
include::src/main/docs/guide/includes/environments-classpath-scanning.adoc[]

```java
@MicronautTest(environments={"foo", "bar"})
```

In addition, although Micronaut itself doesn't scan the classpath, some integrations do (such as JPA and GORM), for these cases you may wish to specify either the application class:

```java
@MicronautTest(application=Application.class)
```

Or the packages:

```java
@MicronautTest(packages="foo.bar")
```

To ensure that entities can be found during classpath scanning.
=== Transaction semantics

include::src/main/docs/guide/includes/transaction.adoc[]

=== Using Mockito Mocks

Expand Down Expand Up @@ -212,14 +197,7 @@ NOTE: When using `TestPropertyProvider` you test must be declared with JUnit's `

=== Refreshing injected beans based on `@Requires` upon properties changes

You can use combine the use of `@Requires` and `@Property`, so that injected beans will be refreshed if there are
configuration changes that affect their `@Requires` condition.

For that to work, the test must be annotated with `@MicronautTest(rebuildContext = true)`. In that case, if there are
changes in any property for a given test, the application context will be rebuilt so that `@Requires` conditions are
re-evaluated again.

For example:
include::src/main/docs/guide/includes/refreshing-requires.adoc[]

.Combining `@Requires` and `@Property` in a `@Refreshable` test class.
[source,java]
Expand Down
29 changes: 4 additions & 25 deletions src/main/docs/guide/kotest.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -191,25 +191,11 @@ include::{kotesttests}/MathServiceTest.kt[]

=== Environments, Classpath Scanning etc.

The `@MicronautTest` annotation supports specifying the environment names the test should run with:
include::src/main/docs/guide/includes/environments-classpath-scanning.adoc[]

```java
@MicronautTest(environments={"foo", "bar"})
```
=== Transaction semantics

In addition, although Micronaut itself doesn't scan the classpath, some integrations do (such as JPA and GORM), for these cases you may wish to specify either the application class:

```java
@MicronautTest(application=Application.class)
```

Or the packages:

```java
@MicronautTest(packages="foo.bar")
```

To ensure that entities can be found during classpath scanning.
include::src/main/docs/guide/includes/transaction.adoc[]

=== Using Mockk Mocks

Expand Down Expand Up @@ -307,14 +293,7 @@ There are a couple caveats to using constructor injection to be aware of.

=== Refreshing injected beans based on `@Requires` upon properties changes

You can use combine the use of `@Requires` and `@Property`, so that injected beans will be refreshed if there are
configuration changes that affect their `@Requires` condition.

For that to work, the test must be annotated with `@MicronautTest(rebuildContext = true)`. In that case, if there are
changes in any property for a given test, the application context will be rebuilt so that `@Requires` conditions are
re-evaluated again.

For example:
include::src/main/docs/guide/includes/refreshing-requires.adoc[]

.Combining `@Requires` and `@Property` in a `@Refreshable` test class.
[source,kotlin]
Expand Down
29 changes: 4 additions & 25 deletions src/main/docs/guide/kotlintest.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -193,25 +193,11 @@ include::{kotlintesttests}/MathServiceTest.kt[]

=== Environments, Classpath Scanning etc.

The `@MicronautTest` annotation supports specifying the environment names the test should run with:
include::src/main/docs/guide/includes/environments-classpath-scanning.adoc[]

```java
@MicronautTest(environments={"foo", "bar"})
```
=== Transaction semantics

In addition, although Micronaut itself doesn't scan the classpath, some integrations do (such as JPA and GORM), for these cases you may wish to specify either the application class:

```java
@MicronautTest(application=Application.class)
```

Or the packages:

```java
@MicronautTest(packages="foo.bar")
```

To ensure that entities can be found during classpath scanning.
include::src/main/docs/guide/includes/transaction.adoc[]

=== Using Mockk Mocks

Expand Down Expand Up @@ -309,14 +295,7 @@ There are a couple caveats to using constructor injection to be aware of.

=== Refreshing injected beans based on `@Requires` upon properties changes

You can use combine the use of `@Requires` and `@Property`, so that injected beans will be refreshed if there are
configuration changes that affect their `@Requires` condition.

For that to work, the test must be annotated with `@MicronautTest(rebuildContext = true)`. In that case, if there are
changes in any property for a given test, the application context will be rebuilt so that `@Requires` conditions are
re-evaluated again.

For example:
include::src/main/docs/guide/includes/refreshing-requires.adoc[]

.Combining `@Requires` and `@Property` in a `@Refreshable` test class.
[source,kotlin]
Expand Down
29 changes: 4 additions & 25 deletions src/main/docs/guide/spock.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -55,25 +55,11 @@ include::{spocktests}/MathServiceSpec.groovy[]

=== Environments, Classpath Scanning etc.

The `@MicronautTest` annotation supports specifying the environment names the test should run with:
include::src/main/docs/guide/includes/environments-classpath-scanning.adoc[]

```java
@MicronautTest(environments=["foo", "bar"])
```
=== Transaction semantics

In addition, although Micronaut itself doesn't scan the classpath, some integrations do (such as JPA and GORM), for these cases you may wish to specify either the application class:

```java
@MicronautTest(application=Application.class)
```

Or the packages:

```java
@MicronautTest(packages="foo.bar")
```

To ensure that entities can be found during classpath scanning.
include::src/main/docs/guide/includes/transaction.adoc[]

=== Using Spock Mocks

Expand Down Expand Up @@ -160,14 +146,7 @@ The above example expects a file located at `src/test/resources/io/micronaut/spo

=== Refreshing injected beans based on `@Requires` upon properties changes

You can use combine the use of `@Requires` and `@Property`, so that injected beans will be refreshed if there are
configuration changes that affect their `@Requires` condition.

For that to work, the test must be annotated with `@MicronautTest(rebuildContext = true)`. In that case, if there are
changes in any property for a given test, the application context will be rebuilt so that `@Requires` conditions are
re-evaluated again.

For example:
include::src/main/docs/guide/includes/refreshing-requires.adoc[]

.Combining `@Requires` and `@Property` in a `@Refreshable` test class.
[source,java]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright 2017-2020 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micronaut.test.spock

import io.micronaut.context.ApplicationContext
import io.micronaut.context.annotation.Property
import io.micronaut.core.util.StringUtils
import io.micronaut.test.annotation.MicronautTest
import io.micronaut.test.spock.entities.Book
import io.micronaut.test.transaction.spring.SpringTransactionTestExecutionListener
import org.springframework.transaction.support.TransactionSynchronizationManager
import spock.lang.Specification
import spock.lang.Stepwise

import javax.inject.Inject

@MicronautTest(rollback = false, packages = "io.micronaut.test.spock.entities")
@HibernateProperties
@Stepwise
class GormTransactionalNoRollbackSpec extends Specification {

@Inject
ApplicationContext applicationContext

def setup() {
// check transaction is present in setup
assert TransactionSynchronizationManager.isSynchronizationActive()
}

def cleanup() {
// check transaction is present in cleanup
assert TransactionSynchronizationManager.isSynchronizationActive()
}

void "bean SpringTransactionTestExecutionListener exists"() {
expect:
applicationContext.containsBean(SpringTransactionTestExecutionListener)
}

void "save book"() {
when:
new Book(name: "BAR").save(failOnError: true, flush: true)

then:
noExceptionThrown()

and:
Book.count() == old(Book.count()) + 1
}

void "book was not rolled back"() {
expect:
Book.count() == 1
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,8 @@ import spock.lang.Stepwise

import javax.inject.Inject

@MicronautTest(transactional = true, rollback = true, packages = "io.micronaut.test.spock.entities")
@Property(name = "hibernate.hbm2ddl.auto", value = "update")
@Property(name = "hibernate.cache.queries", value = StringUtils.FALSE)
@Property(name = "hibernate.cache.use_second_level_cache", value = StringUtils.FALSE)
@Property(name = "hibernate.cache.use_query_cache", value = StringUtils.FALSE)
@Property(name = "hibernate.dataSource.url", value = 'jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE')
@Property(name = "hibernate.dataSource.pooled", value = StringUtils.TRUE)
@Property(name = "hibernate.dataSource.jmxExport", value = StringUtils.TRUE)
@Property(name = "hibernate.dataSource.driverClassName", value = 'org.h2.Driver')
@Property(name = "hibernate.dataSource.username", value = 'sa')
@Property(name = "hibernate.dataSource.password", value = '')
@MicronautTest(packages = "io.micronaut.test.spock.entities")
@HibernateProperties
@Stepwise
class GormTransactionalRollbackSpec extends Specification {

Expand All @@ -50,7 +41,7 @@ class GormTransactionalRollbackSpec extends Specification {
}

def cleanup() {
// check transaction is present in setup
// check transaction is present in cleanup
assert TransactionSynchronizationManager.isSynchronizationActive()
}

Expand All @@ -70,7 +61,7 @@ class GormTransactionalRollbackSpec extends Specification {
Book.count() == old(Book.count()) + 1
}

void "book was rollbacked"() {
void "book was rolled back"() {
expect:
Book.count() == 0
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package io.micronaut.test.spock

import io.micronaut.context.annotation.Property
import io.micronaut.core.util.StringUtils

import java.lang.annotation.Documented
import java.lang.annotation.ElementType
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
import java.lang.annotation.Target

@Retention(RetentionPolicy.RUNTIME)
@Target([ElementType.METHOD, ElementType.TYPE])
@Documented
@Property(name = "hibernate.hbm2ddl.auto", value = "update")
@Property(name = "hibernate.cache.queries", value = StringUtils.FALSE)
@Property(name = "hibernate.cache.use_second_level_cache", value = StringUtils.FALSE)
@Property(name = "hibernate.cache.use_query_cache", value = StringUtils.FALSE)
@Property(name = "hibernate.dataSource.url", value = 'jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE')
@Property(name = "hibernate.dataSource.pooled", value = StringUtils.TRUE)
@Property(name = "hibernate.dataSource.jmxExport", value = StringUtils.TRUE)
@Property(name = "hibernate.dataSource.driverClassName", value = 'org.h2.Driver')
@Property(name = "hibernate.dataSource.username", value = 'sa')
@Property(name = "hibernate.dataSource.password", value = '')
@interface HibernateProperties {}

0 comments on commit 8ac3daf

Please sign in to comment.