1616 */
1717package org.neo4j.connectors.kafka.testing.sink
1818
19+ import com.sun.net.httpserver.HttpExchange
20+ import java.lang.reflect.Parameter
1921import java.util.concurrent.atomic.AtomicBoolean
20- import kotlin.reflect.KFunction0
22+ import kotlin.reflect.KClass
23+ import kotlin.reflect.KFunction
2124import kotlin.reflect.jvm.javaMethod
2225import kotlin.test.assertContains
2326import kotlin.test.assertEquals
2427import kotlin.test.assertFailsWith
2528import kotlin.test.assertFalse
2629import kotlin.test.assertIs
30+ import kotlin.test.assertSame
2731import kotlin.test.assertTrue
2832import org.junit.jupiter.api.AfterEach
2933import org.junit.jupiter.api.Test
3034import org.junit.jupiter.api.extension.ConditionEvaluationResult
3135import org.junit.jupiter.api.extension.ExtensionConfigurationException
3236import org.junit.jupiter.api.extension.ExtensionContext
37+ import org.junit.jupiter.api.extension.ParameterContext
38+ import org.mockito.kotlin.doAnswer
3339import org.mockito.kotlin.doReturn
40+ import org.mockito.kotlin.inOrder
3441import org.mockito.kotlin.mock
42+ import org.mockito.kotlin.verify
3543import org.neo4j.connectors.kafka.testing.KafkaConnectServer
44+ import org.neo4j.driver.Driver
45+ import org.neo4j.driver.Session
3646
3747class Neo4jSinkExtensionTest {
3848
3949 private val extension = Neo4jSinkExtension ()
50+
4051 private val kafkaConnectServer = KafkaConnectServer ()
4152
4253 @AfterEach
@@ -58,14 +69,12 @@ class Neo4jSinkExtensionTest {
5869 kafkaConnectServer.start(
5970 registrationHandler = { exchange ->
6071 if (! handlerCalled.compareAndSet(false , true )) {
61- exchange.sendResponseHeaders(500 , - 1 )
62- exchange.responseBody
63- .bufferedWriter()
64- .write(" expected handler flag to be initially false" )
72+ internalServerError(exchange, " expected handler flag to be initially false" )
6573 return @start true
6674 }
6775 return @start false
68- })
76+ },
77+ )
6978 val environment =
7079 mapOf (
7180 " KAFKA_CONNECT_EXTERNAL_URI" to kafkaConnectServer.address(),
@@ -85,14 +94,12 @@ class Neo4jSinkExtensionTest {
8594 kafkaConnectServer.start(
8695 unregistrationHandler = { exchange ->
8796 if (! handlerCalled.compareAndSet(false , true )) {
88- exchange.sendResponseHeaders(500 , - 1 )
89- exchange.responseBody
90- .bufferedWriter()
91- .write(" expected handler flag to be initially false" )
97+ internalServerError(exchange, " expected handler flag to be initially false" )
9298 return @start true
9399 }
94100 return @start false
95- })
101+ },
102+ )
96103 val environment =
97104 mapOf (
98105 " KAFKA_CONNECT_EXTERNAL_URI" to kafkaConnectServer.address(),
@@ -107,6 +114,93 @@ class Neo4jSinkExtensionTest {
107114 assertTrue(handlerCalled.get(), " unregistration should be successful" )
108115 }
109116
117+ @Test
118+ fun `supports specific parameters` () {
119+ assertTrue(
120+ extension.supportsParameter(
121+ parameterContextForType(Session ::class ),
122+ mock<ExtensionContext >(),
123+ ),
124+ " session parameters should be resolvable" ,
125+ )
126+ assertFalse(
127+ extension.supportsParameter(
128+ parameterContextForType(Thread ::class ),
129+ mock<ExtensionContext >(),
130+ ),
131+ " arbitrary parameters should not be supported" ,
132+ )
133+ }
134+
135+ @Test
136+ fun `resolves Session parameters` () {
137+ val session = mock<Session >()
138+ val driver = mock<Driver > { on { session() } doReturn session }
139+ val extension = Neo4jSinkExtension (driverFactory = { _, _ -> driver })
140+ val extensionContext = extensionContextFor(::validMethod)
141+ extension.evaluateExecutionCondition(extensionContext)
142+
143+ val sessionParam =
144+ extension.resolveParameter(parameterContextForType(Session ::class ), extensionContext)
145+
146+ assertIs<Session >(sessionParam)
147+ assertSame(session, sessionParam)
148+ }
149+
150+ @Test
151+ fun `verifies connectivity if driver is initialized before each test` () {
152+ kafkaConnectServer.start()
153+ val session = mock<Session >()
154+ val environment =
155+ mapOf (
156+ " KAFKA_CONNECT_EXTERNAL_URI" to kafkaConnectServer.address(),
157+ )
158+ val driver =
159+ mock<Driver > {
160+ on { session() } doReturn session
161+ on { verifyConnectivity() } doAnswer {}
162+ }
163+ val extension =
164+ Neo4jSinkExtension (
165+ envAccessor = environment::get,
166+ driverFactory = { _, _ -> driver },
167+ )
168+ val extensionContext = extensionContextFor(::onlyKafkaExternalUriFromEnvMethod)
169+ extension.evaluateExecutionCondition(extensionContext)
170+ extension.resolveParameter(parameterContextForType(Session ::class ), extensionContext)
171+
172+ extension.beforeEach(extensionContext)
173+
174+ verify(driver).verifyConnectivity()
175+ }
176+
177+ @Test
178+ fun `closes Driver and Session after each test` () {
179+ kafkaConnectServer.start()
180+ val session = mock<Session >()
181+ val environment =
182+ mapOf (
183+ " KAFKA_CONNECT_EXTERNAL_URI" to kafkaConnectServer.address(),
184+ )
185+ val driver = mock<Driver > { on { session() } doReturn session }
186+ val extension =
187+ Neo4jSinkExtension (
188+ envAccessor = environment::get,
189+ driverFactory = { _, _ -> driver },
190+ )
191+ val extensionContext = extensionContextFor(::onlyKafkaExternalUriFromEnvMethod)
192+ extension.evaluateExecutionCondition(extensionContext)
193+ extension.resolveParameter(parameterContextForType(Session ::class ), extensionContext)
194+ extension.beforeEach(extensionContext)
195+
196+ extension.afterEach(extensionContext)
197+
198+ inOrder(session, driver) {
199+ verify(session).close()
200+ verify(driver).close()
201+ }
202+ }
203+
110204 @Test
111205 fun `stops execution evaluation if annotation is not found` () {
112206 val exception =
@@ -220,13 +314,22 @@ class Neo4jSinkExtensionTest {
220314 )
221315 }
222316
223- private fun extensionContextFor (method : KFunction0 <Unit >) =
317+ private fun parameterContextForType (parameterType : KClass <* >): ParameterContext {
318+ val param = mock<Parameter > { on { type } doReturn parameterType.java }
319+ return mock<ParameterContext > { on { parameter } doReturn param }
320+ }
321+
322+ private fun extensionContextFor (method : KFunction <Unit >) =
224323 mock<ExtensionContext > { on { requiredTestMethod } doReturn method.javaMethod }
225324
226- @Suppress(" UNUSED" ) fun missingAnnotationMethod () {}
325+ private fun internalServerError (exchange : HttpExchange , error : String ) {
326+ exchange.sendResponseHeaders(500 , - 1 )
327+ exchange.responseBody.bufferedWriter().write(error)
328+ }
227329
228330 @Neo4jSink(
229331 kafkaConnectExternalUri = " http://example.com" ,
332+ neo4jExternalUri = " neo4j://example.com" ,
230333 neo4jUri = " neo4j://example.com" ,
231334 neo4jUser = " user" ,
232335 neo4jPassword = " password" ,
@@ -237,6 +340,7 @@ class Neo4jSinkExtensionTest {
237340 fun validMethod () {}
238341
239342 @Neo4jSink(
343+ neo4jExternalUri = " neo4j://example.com" ,
240344 neo4jUri = " neo4j://example.com" ,
241345 neo4jUser = " user" ,
242346 neo4jPassword = " password" ,
@@ -250,6 +354,8 @@ class Neo4jSinkExtensionTest {
250354 @Suppress(" UNUSED" )
251355 fun envBackedMethod () {}
252356
357+ @Suppress(" UNUSED" ) fun missingAnnotationMethod () {}
358+
253359 @Neo4jSink(
254360 kafkaConnectExternalUri = " http://example.com" ,
255361 neo4jUri = " neo4j://example.com" ,
0 commit comments