Skip to content

Commit dfe4649

Browse files
committed
refactor: migrate :src:protocol:bolt Groovy tests to Kotlin
1 parent bf18733 commit dfe4649

2 files changed

Lines changed: 139 additions & 139 deletions

File tree

src/protocol/bolt/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,5 @@ dependencies {
2828
implementation("com.fasterxml.jackson.core:jackson-databind")
2929

3030
testImplementation(testFixtures(projects.src.core))
31+
testImplementation("io.mockk:mockk")
3132
}

src/protocol/bolt/src/test/kotlin/org/apache/jmeter/protocol/bolt/sampler/BoltSamplerTest.kt

Lines changed: 138 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,19 @@
1717

1818
package org.apache.jmeter.protocol.bolt.sampler
1919

20+
import io.mockk.every
21+
import io.mockk.justRun
22+
import io.mockk.mockk
2023
import org.apache.jmeter.protocol.bolt.config.BoltConnectionElement
2124
import org.apache.jmeter.samplers.Entry
25+
import org.apache.jmeter.samplers.SampleResult
2226
import org.apache.jmeter.threads.JMeterContextService
2327
import org.apache.jmeter.threads.JMeterVariables
28+
import org.junit.jupiter.api.Assertions.assertEquals
29+
import org.junit.jupiter.api.Assertions.assertFalse
30+
import org.junit.jupiter.api.Assertions.assertTrue
31+
import org.junit.jupiter.api.BeforeEach
32+
import org.junit.jupiter.api.Test
2433
import org.neo4j.driver.Driver
2534
import org.neo4j.driver.Record
2635
import org.neo4j.driver.Result
@@ -29,166 +38,156 @@ import org.neo4j.driver.exceptions.ClientException
2938
import org.neo4j.driver.summary.ResultSummary
3039
import org.neo4j.driver.summary.SummaryCounters
3140

32-
import spock.lang.Specification
41+
class BoltSamplerTest {
42+
lateinit var sampler: BoltSampler
43+
lateinit var entry: Entry
44+
lateinit var session: Session
3345

34-
class BoltSamplerSpec extends Specification {
35-
36-
BoltSampler sampler
37-
Entry entry
38-
Session session
39-
40-
def setup() {
41-
sampler = new BoltSampler()
42-
entry = new Entry()
43-
def driver = Mock(Driver)
44-
def boltConfig = new BoltConnectionElement()
45-
def variables = new JMeterVariables()
46+
@BeforeEach
47+
fun setup() {
48+
sampler = BoltSampler()
49+
entry = Entry()
50+
session = mockk<Session> {
51+
justRun { close() }
52+
}
53+
val driver = mockk<Driver> {
54+
every { session(any()) } returns session
55+
}
56+
val boltConfig = BoltConnectionElement()
57+
val variables = JMeterVariables()
4658
// ugly but could not find a better way to pass the driver to the sampler...
4759
variables.putObject(BoltConnectionElement.BOLT_CONNECTION, driver)
48-
JMeterContextService.getContext().setVariables(variables)
60+
JMeterContextService.getContext().variables = variables
4961
entry.addConfigElement(boltConfig)
50-
session = Mock(Session)
51-
driver.session(_) >> session
5262
}
5363

54-
def "should execute return success on successful query"() {
55-
given:
56-
sampler.setCypher("MATCH x")
57-
session.run("MATCH x", [:], _) >> getEmptyQueryResult()
58-
when:
59-
def response = sampler.sample(entry)
60-
then:
61-
response.isSuccessful()
62-
response.isResponseCodeOK()
63-
def str = response.getResponseDataAsString()
64-
str.contains("Summary:")
65-
str.endsWith("Records: Skipped")
66-
response.getSampleCount() == 1
67-
response.getErrorCount() == 0
68-
// The sampler was executed, so start and end times should be set
69-
response.getStartTime() > 0
70-
response.getEndTime() > 0
64+
@Test
65+
fun `should execute return success on successful query`() {
66+
sampler.cypher = "MATCH x"
67+
every {
68+
session.run("MATCH x", mapOf(), any())
69+
} returns getEmptyQueryResult()
70+
val response = sampler.sample(entry)
71+
72+
assertSuccessResult(response, "Records: Skipped")
73+
}
74+
75+
private fun assertSuccessResult(response: SampleResult, responseDataTail: String) {
76+
val str = response.responseDataAsString
77+
assertTrue(str.contains("Summary:"), "response contains 'Summary:', got '$str'")
78+
assertTrue(str.endsWith(responseDataTail), "response ends with '$responseDataTail', got '$str'")
79+
assertTrue(response.isSuccessful, ".isSuccessful()")
80+
assertTrue(response.isResponseCodeOK, ".isResponseCodeOK()")
81+
assertEquals(1, response.sampleCount, ".sampleCount")
82+
assertEquals(0, response.errorCount, ".errorCount")
83+
assertSamplerStarted(response)
84+
}
85+
86+
private fun assertSamplerStarted(response: SampleResult) {
87+
assertTrue(response.startTime > 0, "The sampler was executed, so start and end times should be set")
88+
assertTrue(response.endTime > 0, "The sampler was executed, so start and end times should be set")
7189
}
7290

73-
def "should not display results by default"() {
74-
given:
75-
sampler.setCypher("MATCH x")
76-
session.run("MATCH x", [:], _) >> getPopulatedQueryResult()
77-
when:
78-
def response = sampler.sample(entry)
79-
then:
80-
response.isSuccessful()
81-
response.isResponseCodeOK()
82-
def str = response.getResponseDataAsString()
83-
str.contains("Summary:")
84-
str.endsWith("Records: Skipped")
85-
response.getSampleCount() == 1
86-
response.getErrorCount() == 0
91+
private fun assertFailureResult(
92+
response: SampleResult,
93+
responseCode: String,
94+
message: String,
95+
samplerStarted: Boolean
96+
) {
97+
val str = response.responseDataAsString
98+
assertFalse(str.contains("Summary:"), "response contains 'Summary:', got $str")
99+
assertTrue(str.contains(message), "response contains '$message', got $str")
100+
assertFalse(response.isSuccessful, ".isSuccessful()")
101+
assertFalse(response.isResponseCodeOK, ".isResponseCodeOK()")
102+
assertEquals(responseCode, response.responseCode, ".responseCode")
103+
assertEquals(1, response.sampleCount, ".sampleCount")
104+
assertEquals(1, response.errorCount, ".errorCount")
105+
if (samplerStarted) {
106+
assertSamplerStarted(response)
107+
} else {
108+
assertSamplerNotStarted(response)
109+
}
87110
}
88111

89-
def "should display results if asked"() {
90-
given:
91-
sampler.setCypher("MATCH x")
92-
sampler.setRecordQueryResults(true)
93-
session.run("MATCH x", [:], _) >> getPopulatedQueryResult()
94-
when:
95-
def response = sampler.sample(entry)
96-
then:
97-
response.isSuccessful()
98-
response.isResponseCodeOK()
99-
def str = response.getResponseDataAsString()
100-
str.contains("Summary:")
101-
str.endsWith("Mock for type 'Record'")
102-
response.getSampleCount() == 1
103-
response.getErrorCount() == 0
104-
// The sampler was executed, so start and end times should be set
105-
response.getStartTime() > 0
106-
response.getEndTime() > 0
112+
private fun assertSamplerNotStarted(response: SampleResult) {
113+
assertEquals(0, response.startTime, "The sampler fails at parameter preparation, so no time is recorded")
114+
assertEquals(0, response.endTime, "The sampler fails at parameter preparation, so no time is recorded")
107115
}
108116

109-
def "should return error on failed query"() {
110-
given:
111-
sampler.setCypher("MATCH x")
112-
session.run("MATCH x", [:], _) >> { throw new RuntimeException("a message") }
113-
when:
114-
def response = sampler.sample(entry)
115-
then:
116-
!response.isSuccessful()
117-
!response.isResponseCodeOK()
118-
response.getResponseCode() == "500"
119-
def str = response.getResponseDataAsString()
120-
str.contains("a message")
121-
response.getSampleCount() == 1
122-
response.getErrorCount() == 1
123-
// The sampler was executed, so start and end times should be set
124-
response.getStartTime() > 0
125-
response.getEndTime() > 0
117+
@Test
118+
fun `should not display results by default`() {
119+
sampler.cypher = "MATCH x"
120+
every {
121+
session.run("MATCH x", mapOf(), any())
122+
} returns getPopulatedQueryResult()
123+
val response = sampler.sample(entry)
124+
125+
assertSuccessResult(response, "Records: Skipped")
126126
}
127127

128-
def "should return error on invalid parameters"() {
129-
given:
130-
sampler.setCypher("MATCH x")
131-
sampler.setParams("{invalid}")
132-
when:
133-
def response = sampler.sample(entry)
134-
then:
135-
!response.isSuccessful()
136-
!response.isResponseCodeOK()
137-
response.getResponseCode() == "500"
138-
def str = response.getResponseDataAsString()
139-
str.contains("Unexpected character")
140-
response.getSampleCount() == 1
141-
response.getErrorCount() == 1
142-
// The sampler fails at parameter preparation, so no time is recorded
143-
response.getStartTime() == 0
144-
response.getEndTime() == 0
145-
response.getTime() == 0
128+
@Test
129+
fun `should display results if asked`() {
130+
sampler.cypher = "MATCH x"
131+
sampler.isRecordQueryResults = true
132+
every {
133+
session.run("MATCH x", mapOf(), any())
134+
} returns getPopulatedQueryResult()
135+
val response = sampler.sample(entry)
136+
assertSuccessResult(response, "Mock for type 'Record'")
146137
}
147138

148-
def "should return db error code"() {
149-
given:
150-
sampler.setCypher("MATCH x")
151-
session.run("MATCH x", [:], _) >> { throw new ClientException("a code", "a message") }
152-
when:
153-
def response = sampler.sample(entry)
154-
then:
155-
response.getResponseCode() == "a code"
139+
@Test
140+
fun `should return error on failed query`() {
141+
sampler.cypher = "MATCH x"
142+
every { session.run("MATCH x", mapOf(), any()) } throws RuntimeException("a message")
143+
val response = sampler.sample(entry)
144+
145+
assertFailureResult(response, "500", "a message", samplerStarted = true)
156146
}
157147

158-
def "should ignore invalid timeout values"() {
159-
given:
160-
sampler.setCypher("MATCH x")
161-
sampler.setTxTimeout(-1)
162-
session.run("MATCH x", [:], _) >> getEmptyQueryResult()
163-
when:
164-
def response = sampler.sample(entry)
165-
then:
166-
response.isSuccessful()
167-
response.isResponseCodeOK()
168-
def str = response.getResponseDataAsString()
169-
str.contains("Summary:")
170-
str.endsWith("Records: Skipped")
171-
response.getSampleCount() == 1
172-
response.getErrorCount() == 0
148+
@Test
149+
fun `should return error on invalid parameters`() {
150+
sampler.cypher = "MATCH x"
151+
sampler.params = "{invalid}"
152+
val response = sampler.sample(entry)
153+
154+
assertFailureResult(response, "500", "Unexpected character", samplerStarted = false)
173155
}
174156

175-
def getEmptyQueryResult() {
176-
def queryResult = Mock(Result)
177-
def summary = Mock(ResultSummary)
178-
queryResult.consume() >> summary
179-
SummaryCounters counters = Mock(SummaryCounters)
180-
summary.counters() >> counters
181-
return queryResult
157+
@Test
158+
fun `should return db error code`() {
159+
sampler.cypher = "MATCH x"
160+
every { session.run("MATCH x", mapOf(), any()) } throws ClientException("a code", "a message")
161+
val response = sampler.sample(entry)
162+
assertEquals("a code", response.responseCode)
182163
}
183164

184-
def getPopulatedQueryResult() {
185-
def queryResult = Mock(Result)
186-
def summary = Mock(ResultSummary)
187-
def list = [Mock(Record), Mock(Record), Mock(Record)]
188-
queryResult.consume() >> summary
189-
queryResult.list() >> list
190-
SummaryCounters counters = Mock(SummaryCounters)
191-
summary.counters() >> counters
192-
return queryResult
165+
@Test
166+
fun `should ignore invalid timeout values`() {
167+
sampler.cypher = "MATCH x"
168+
sampler.txTimeout = -1
169+
every { session.run("MATCH x", mapOf(), any()) } returns getEmptyQueryResult()
170+
val response = sampler.sample(entry)
171+
assertSuccessResult(response, "Records: Skipped")
193172
}
173+
174+
private fun getEmptyQueryResult() =
175+
mockk<Result> {
176+
every { consume() } returns mockk<ResultSummary> {
177+
every { counters() } returns mockk<SummaryCounters>(relaxed = true)
178+
}
179+
}
180+
181+
@Suppress("LABEL_NAME_CLASH")
182+
private fun getPopulatedQueryResult() =
183+
mockk<Result> {
184+
every { consume() } returns mockk<ResultSummary> {
185+
every { counters() } returns mockk<SummaryCounters>(relaxed = true)
186+
}
187+
every { list() } returns listOf(
188+
mockk<Record> { every { this@mockk.toString() } returns "Mock for type 'Record'" },
189+
mockk<Record> { every { this@mockk.toString() } returns "Mock for type 'Record'" },
190+
mockk<Record> { every { this@mockk.toString() } returns "Mock for type 'Record'" },
191+
)
192+
}
194193
}

0 commit comments

Comments
 (0)