|
1 | 1 | == Testing against the Neo4j harness |
2 | 2 |
|
3 | | -First of all, you have to include the test harness in your dependencies. |
4 | | -Pick either community edition or enterprise edition. |
| 3 | +We provide a special module that brings in the community edition of the Neo4j harness |
| 4 | +and some additional utilities that hopefully make your life easier. |
5 | 5 |
|
6 | | -Here's the community edition: |
| 6 | +[source,xml] |
| 7 | +.pom.xml |
| 8 | +---- |
| 9 | +<dependency> |
| 10 | + <groupId>org.neo4j.driver</groupId> |
| 11 | + <artifactId>neo4j-java-driver-test-harness-spring-boot-autoconfigure</artifactId> |
| 12 | + <version>${neo4j-java-driver-spring-boot-starter.version}</version> |
| 13 | + <scope>test</scope> |
| 14 | +</dependency> |
| 15 | +---- |
| 16 | + |
| 17 | +If you need the enterprise edition, bring in the module like this: |
7 | 18 |
|
8 | 19 | [source,xml] |
9 | 20 | .pom.xml |
10 | 21 | ---- |
11 | 22 | <dependency> |
12 | | - <groupId>org.neo4j.test</groupId> |
13 | | - <artifactId>neo4j-harness</artifactId> |
14 | | - <version>${neo4j.version}</version> |
15 | | - <scope>test</scope> |
| 23 | + <groupId>org.neo4j.driver</groupId> |
| 24 | + <artifactId>neo4j-java-driver-test-harness-spring-boot-autoconfigure</artifactId> |
| 25 | + <version>${neo4j-java-driver-spring-boot-starter.version}</version> |
| 26 | + <scope>test</scope> |
| 27 | + <exclusions> |
| 28 | + <exclusion> |
| 29 | + <groupId>org.neo4j.test</groupId> |
| 30 | + <artifactId>neo4j-harness</artifactId> |
| 31 | + </exclusion> |
| 32 | + </exclusions> |
| 33 | +</dependency> |
| 34 | +<dependency> |
| 35 | + <groupId>com.neo4j.test</groupId> |
| 36 | + <artifactId>neo4j-harness-enterprise</artifactId> |
| 37 | + <version>${neo4j.version}</version> |
| 38 | + <scope>test</scope> |
| 39 | + <exclusions> |
| 40 | + <exclusion> |
| 41 | + <groupId>org.slf4j</groupId> |
| 42 | + <artifactId>slf4j-nop</artifactId> |
| 43 | + </exclusion> |
| 44 | + </exclusions> |
16 | 45 | </dependency> |
17 | 46 | ---- |
18 | 47 |
|
19 | 48 | That brings a ton of dependencies. |
20 | 49 | The advantage of it: It starts very fast. |
21 | 50 | If you don't want to have the dependencies and can live with a slower start, we recommend https://www.testcontainers.org/modules/databases/neo4j/[Testcontainers]. |
22 | 51 |
|
23 | | -=== Starting up the Neo4j harness |
| 52 | +They are easy to use and can be configured as shown in <<option1,option 1 below>> as well. |
| 53 | + |
| 54 | +=== Neo4j 3.5 or Neo4j 4.0? |
| 55 | + |
| 56 | +Neo4j 3.5 and 4.0 have different requirements. |
| 57 | +Neo4j 4.0 requires at least JDK 11. |
| 58 | +We understand that not all of you are ready to go beyond JDK 8 (but you should). |
| 59 | +Therefore we decided to build the Test harness support by default against Neo4j 3.5 and JDK 8. |
| 60 | + |
| 61 | +To use Neo4j 4.0 as in the following examples, please add this to your build file |
| 62 | + |
| 63 | +[source,xml] |
| 64 | +.pom.xml |
| 65 | +---- |
| 66 | +<dependencyManagement> |
| 67 | + <dependencies> |
| 68 | + <dependency> |
| 69 | + <groupId>org.neo4j.test</groupId> |
| 70 | + <artifactId>neo4j-harness</artifactId> |
| 71 | + <version>4.0.0</version> |
| 72 | + </dependency> |
| 73 | + </dependencies> |
| 74 | +</dependencyManagement> |
| 75 | +---- |
| 76 | + |
| 77 | +Be aware that the type of the 4.0 test harness is `org.neo4j.harness.Neo4j`. |
| 78 | +The following examples use 4.0 (`org.neo4j.harness.Neo4j`) but are applicable to `ServerControlls`, too. |
| 79 | + |
| 80 | +=== Starting up the Neo4j harness and making Spring aware |
24 | 81 |
|
25 | 82 | There many different options. |
26 | | -Here's a simple JUnit 5 variant: |
| 83 | +The main question is always: *How to make Spring Boot aware that it should use different configuration properties?* |
| 84 | + |
| 85 | +[[option1]] |
| 86 | +==== Option 1: Add the embedded server as a Spring bean (recommended approach) |
| 87 | + |
| 88 | +This is shown have this as `MoviesServiceAlt2Test`. |
27 | 89 |
|
28 | 90 | [source,java] |
29 | | -.MoviesServiceTest.java |
| 91 | +[[simple-example]] |
| 92 | +.MoviesServiceAlt1Test.java |
30 | 93 | ---- |
31 | | -class MoviesServiceTest { |
| 94 | +@SpringBootTest |
| 95 | +class MoviesServiceAlt1Test { |
| 96 | +
|
| 97 | + @TestConfiguration // <1> |
| 98 | + static class TestHarnessConfig { |
| 99 | +
|
| 100 | + @Bean // <2> |
| 101 | + public Neo4j neo4j() { |
| 102 | + return Neo4jBuilders.newInProcessBuilder() |
| 103 | + .withDisabledServer() // No need for http |
| 104 | + .withFixture("CREATE (TheMatrixReloaded:Movie {title:'The Matrix Reloaded', released:2003, tagline:'Free your mind'})") |
| 105 | + .build(); |
| 106 | +
|
| 107 | + // For enterprise use |
| 108 | + // return com.neo4j.harness.EnterpriseNeo4jBuilders.newInProcessBuilder() |
| 109 | + // .newInProcessBuilder() |
| 110 | + // .build(); |
| 111 | + } |
| 112 | + } |
32 | 113 |
|
33 | | - private static ServerControls embeddedDatabaseServer; |
| 114 | + @Test |
| 115 | + void testSomethingWithTheDriver(@Autowired Driver driver) { |
| 116 | + } |
| 117 | +} |
| 118 | +---- |
| 119 | +<.> This is a test configuration only applicable for this test |
| 120 | +<.> This turns the embedded instance into a Spring Bean, bound to Springs lifecycle |
34 | 121 |
|
35 | | - @BeforeAll |
36 | | - static void initializeNeo4j() { |
37 | | - embeddedDatabaseServer = TestServerBuilders |
38 | | - .newInProcessBuilder() |
39 | | - .newServer(); |
| 122 | +The autoconfiguration module for the test harness makes the starter aware of the harness and reconfigures the driver to use it. |
| 123 | +This would be the recommended way of doing things. |
| 124 | + |
| 125 | +[[option2]] |
| 126 | +==== Option 2: Use the provided harness instance |
| 127 | + |
| 128 | +`MoviesServiceAlt2Test.java` demonstrates the fully automatic configuration of test harness and driver: |
| 129 | + |
| 130 | +[source,java] |
| 131 | +[[simple-example]] |
| 132 | +.MoviesServiceAlt2Test.java |
| 133 | +---- |
| 134 | +@SpringBootTest |
| 135 | +public class MoviesServiceAlt2Test { |
| 136 | +
|
| 137 | + @BeforeEach |
| 138 | + void prepareDatabase(@Autowired Neo4j neo4j) { // <.> |
| 139 | + neo4j.defaultDatabaseService().executeTransactionally( |
| 140 | + "CREATE (TheMatrix:Movie {title:'The Matrix', released:1999, tagline:'Welcome to the Real World'})" |
| 141 | + ); |
40 | 142 | } |
41 | 143 |
|
42 | | - @AfterAll |
43 | | - static void closeNeo4j() { |
44 | | - embeddedDatabaseServer.close(); |
| 144 | + @Test |
| 145 | + void testSomethingWithTheDriver(@Autowired Driver driver) { |
45 | 146 | } |
46 | 147 | } |
47 | 148 | ---- |
| 149 | +<.> As you don't have access to the builder, you have to provide your fixtures through the embedded database service. |
| 150 | + |
| 151 | +This may come in handy in some scenarios, but generally, using the builder API as shown above is preferable. |
| 152 | +On the plus side: The automatic configuration of the harness takes care of disabling the embedded webserver (for Neo4j 4.0+). |
48 | 153 |
|
49 | | -== Option a: Make Spring Boot aware of the URL of the embedded server |
| 154 | +[[option3]] |
| 155 | +==== Option 3: Start Neo4j outside Spring and apply its URL to configuration |
50 | 156 |
|
51 | | -In either case, the real issue you have to solve during testing is: |
52 | | -*How to make Spring Boot aware that it should use different configuration properties?* |
| 157 | +Here we start the embedded instance from the JUnit 5 context and |
| 158 | +than use an `org.springframework.context.ApplicationContextInitializer` to apply `TestPropertyValues` to the Spring environment. |
53 | 159 |
|
54 | | -We recommend using a custom `org.springframework.context.ApplicationContextInitializer` on a `@SpringBootTest` like this: |
| 160 | +NOTE: You don't actually need `neo4j-java-driver-test-harness-spring-boot-autoconfigure` for this solution. It's enough to have the |
| 161 | + Test harness - either 3.5.x or 4.0.x or Community or enterprise edition on the classpath. |
| 162 | + If you have the test harness autoconfiguration support on the classpath, you have to explicitly disable it. |
55 | 163 |
|
56 | 164 | [source,java] |
57 | 165 | [[simple-example]] |
58 | | -.MoviesServiceTest.java |
| 166 | +.MoviesServiceAlt3Test.java |
59 | 167 | ---- |
60 | 168 | @SpringBootTest |
| 169 | +@EnableAutoConfiguration(exclude = { Neo4jTestHarnessAutoConfiguration.class }) // <.> |
61 | 170 | @ContextConfiguration(initializers = { MoviesServiceTest.Initializer.class }) |
62 | | -class MoviesServiceTest { |
| 171 | +class MoviesServiceAlt3Test { |
63 | 172 |
|
64 | | - private static ServerControls embeddedDatabaseServer; |
| 173 | + private static Neo4j embeddedDatabaseServer; |
| 174 | +
|
| 175 | + @BeforeAll |
| 176 | + static void initializeNeo4j() { // <.> |
| 177 | + embeddedDatabaseServer = TestServerBuilders |
| 178 | + .newInProcessBuilder() |
| 179 | + .withDisabledServer() // <.> |
| 180 | + .withFixture("CREATE (TheMatrix:Movie {title:'The Matrix', released:1999, tagline:'Welcome to the Real World'})") |
| 181 | + .newServer(); |
| 182 | + } |
| 183 | +
|
| 184 | + @AfterAll |
| 185 | + static void closeNeo4j() { // <.> |
| 186 | + embeddedDatabaseServer.close(); |
| 187 | + } |
65 | 188 |
|
66 | 189 | static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { |
67 | 190 | public void initialize(ConfigurableApplicationContext configurableApplicationContext) { |
68 | 191 |
|
69 | | - TestPropertyValues.of( |
| 192 | + TestPropertyValues.of( // <.> |
70 | 193 | "org.neo4j.driver.uri=" + embeddedDatabaseServer.boltURI().toString(), |
71 | 194 | "org.neo4j.driver.authentication.password=" |
72 | 195 | ).applyTo(configurableApplicationContext.getEnvironment()); |
73 | 196 | } |
74 | 197 | } |
| 198 | +
|
| 199 | + @Test |
| 200 | + void testSomethingWithTheDriver(@Autowired Driver driver) { |
| 201 | + } |
75 | 202 | } |
76 | 203 | ---- |
| 204 | +<.> Disable the autoconfiguration (only needed if you have `neo4j-java-driver-test-harness-spring-boot-autoconfigure` on the classpath) |
| 205 | +<.> Use a JUnit `BeforeAll` to boot Neo4j |
| 206 | +<.> The driver uses only the Bolt port, not the http port, so we don't need the embedded webserver (that option is only available in Neo4j Harness 4.0+) |
| 207 | +<.> Close it in an `AfterAll` |
| 208 | +<.> This the essential part: Apply the new configuration values |
77 | 209 |
|
78 | | -== Option b: Add your own driver bean to the context |
| 210 | +This is a good solution It works well with both Community and enterprise edition and decouples the creation of the server from configuring the client. |
| 211 | +The downside of it: You have to configure a lot of stuff manually and your mileage may vary. |
79 | 212 |
|
80 | | -We have this as `MoviesServiceAltTest`. |
81 | | -While the configuration seems less complex, it changes more than just the url: |
82 | | -Having a driver bean of your own in the context, disables the starter. |
83 | | -That is of course ok, but you might end up with a very different configuration in test than in production. |
84 | | -For example, you'll notice that in `MoviesServiceAltTest`, the driver does not use Slf4j logging, but it's own default. |
| 213 | +==== Running your own driver bean |
85 | 214 |
|
86 | | -Option a only adds properties with higher values onto the default ones. |
87 | | -So, if you have configured more options of the driver in your `application.properties` or else, they still get applied. |
88 | | -That is not the case for you own Driver bean. |
| 215 | +You can always fall back to create your own driver bean, but that actually disables the starter for the driver. |
| 216 | +That is of course ok, but you might end up with a very different configuration in test than in production. |
| 217 | +For example the driver will not use Spring logging, but its own default. |
0 commit comments