Skip to content

Commit

Permalink
Merge pull request #2 from asarkar/feature/issue-1
Browse files Browse the repository at this point in the history
Close #1: Support EmbeddedRedisConfigurer bean
  • Loading branch information
asarkar authored Nov 13, 2020
2 parents 6f6ea6d + 3d64b9d commit 37144f2
Show file tree
Hide file tree
Showing 10 changed files with 148 additions and 54 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ public class AutoConfigureWithRandomPortsTest {

If you want to configure the `RedisServer` before it's started, provide an implementation for
[EmbeddedRedisConfigurer](src/main/kotlin/com/asarkar/spring/test/redis/EmbeddedRedisConfigurer.kt), and set the
class name in the annotation element `serverConfigurerClass`.
class name in the annotation element `serverConfigurerClass`. If a Spring bean of this type exists, it'll be used;
otherwise, a new instance will be created using the public no-argument constructor.

See KDoc for more details.

Expand Down
12 changes: 8 additions & 4 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,13 @@ tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
}
}

tasks.withType<org.jetbrains.dokka.gradle.DokkaTask> {
outputFormat = "html"
outputDirectory = "$buildDir/javadoc"
tasks.dokkaHtml.configure {
outputDirectory.set(buildDir.resolve("javadoc"))
dokkaSourceSets.configureEach {
jdkVersion.set(8)
skipEmptyPackages.set(true)
platform.set(org.jetbrains.dokka.Platform.jvm)
}
}

tasks.test {
Expand All @@ -71,7 +75,7 @@ val kdocJar by tasks.creating(Jar::class) {
group = JavaBasePlugin.DOCUMENTATION_GROUP
description = "Creates KDoc"
archiveClassifier.set("javadoc")
from(tasks.dokka)
from(tasks.dokkaHtml)
}

tasks.jar.configure {
Expand Down
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ embeddedRedisVersion=0.7.3
lettuceVersion=6.0.1.RELEASE
jUnitVersion=5.7.0
kotlinVersion=1.4.10
dokkaPluginVersion=0.10.1
dokkaPluginVersion=1.4.10.2
ktlintVersion=9.4.0
bintrayPluginVersion=1.8.5

projectGroup=com.asarkar.spring
projectVersion=1.0.0
projectVersion=1.1.0
projectDescription=Starts a Redis server and makes the port available as Spring Boot environment property
projectLabels=spring, spring-boot, redis, embedded-redis, test, integration-test
licenseName=Apache-2.0
Expand Down
5 changes: 5 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
pluginManagement {
repositories {
gradlePluginPortal()
jcenter()
}

val kotlinVersion: String by settings
val dokkaPluginVersion: String by settings
val ktlintVersion: String by settings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import java.lang.annotation.Inherited

/**
* Annotation for test classes that want to start a Redis server as part of the Spring application Context.
*
* @property serverConfigurerClass [EmbeddedRedisConfigurer] implementation class. Defaults to empty string.
* @property port Redis server port. Defaults to 6379. Set 0 to use a random port.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import redis.embedded.RedisServerBuilder

/**
* Class that gets called with a `RedisServerBuilder` giving the user a chance to configure the server before it's
* started. Implementations must have a public no-argument constructor.
* started. If a Spring bean of this type exists, it'll be used; otherwise, a new instance will be created using
* the public no-argument constructor.
*
* @author Abhijit Sarkar
* @since 1.0.0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.asarkar.spring.test.redis

import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.context.SmartLifecycle
import org.springframework.util.ReflectionUtils
Expand All @@ -15,7 +16,10 @@ open class EmbeddedRedisLifecycle : SmartLifecycle {
@Value("\${embedded-redis.port:-1}")
var port: Int = -1

lateinit var redisServer: RedisServer
@Autowired(required = false)
private var serverConfigurerBean: EmbeddedRedisConfigurer? = null

private lateinit var redisServer: RedisServer

override fun start() {
if (isRunning || port <= 0) return
Expand All @@ -31,6 +35,9 @@ open class EmbeddedRedisLifecycle : SmartLifecycle {
private fun serverConfigurer(): EmbeddedRedisConfigurer? {
return if (serverConfigurerClass.isNotEmpty()) {
val clazz = Class.forName(serverConfigurerClass)
if (serverConfigurerBean != null) {
return serverConfigurerBean
}
return try {
ReflectionUtils.accessibleConstructor(clazz as Class<EmbeddedRedisConfigurer>)
.newInstance()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,13 @@ package com.asarkar.spring.test.redis

import io.lettuce.core.RedisClient
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.test.context.SpringBootTest
import redis.embedded.RedisServerBuilder
import java.nio.file.Files
import java.nio.file.Paths
import kotlin.random.Random

private val charPool: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
private val file = Paths.get(AutoConfigureWithRandomPortsTest::class.java.getResource("/").toURI())
.let { testPath ->
generateSequence(testPath) {
if (Files.isDirectory(it) && Files.exists(it.resolve("build.gradle.kts"))) {
null
} else {
it.parent
}
}
.take(10) // should be plenty
.toList()
.last()
.resolve("build")
.resolve(
(1..6)
.map { Random.nextInt(0, charPool.size) }
.map(charPool::get)
.joinToString("")
)
}

@SpringBootTest
@AutoConfigureEmbeddedRedis(
port = 0,
serverConfigurerClass = "com.asarkar.spring.test.redis.TestEmbeddedRedisConfigurer"
port = 0
)
class AutoConfigureWithRandomPortsTest {
@Value("\${embedded-redis.port:-1}")
Expand All @@ -50,20 +21,5 @@ class AutoConfigureWithRandomPortsTest {
val syncCommands = redisClient.connect().sync()
syncCommands.set("key", "value")
assertThat(syncCommands.get("key")).isEqualTo("value")
assertThat(Files.exists(file)).isTrue
}

@AfterEach
fun afterEach() {
Files.deleteIfExists(file)
}
}

class TestEmbeddedRedisConfigurer : EmbeddedRedisConfigurer {
private val log = LoggerFactory.getLogger(TestEmbeddedRedisConfigurer::class.java)

override fun configure(builder: RedisServerBuilder) {
Files.createFile(file)
.also { log.info("Created file: {}", it.toAbsolutePath()) }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.asarkar.spring.test.redis

import io.lettuce.core.RedisClient
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Import
import redis.embedded.RedisServerBuilder

@SpringBootTest
@AutoConfigureEmbeddedRedis(
port = 0,
serverConfigurerClass = "com.asarkar.spring.test.redis.TestEmbeddedRedisConfigurerBean"
)
@Import(EmbeddedRedisConfigurerBeanTestConfiguration::class)
class EmbeddedRedisConfigurerBeanTest {
@Value("\${embedded-redis.port:-1}")
private var port: Int = -1

@Autowired
private lateinit var embeddedRedisConfigurer: TestEmbeddedRedisConfigurerBean

@Test
fun testEmbeddedRedisConfigurer() {
val redisClient = RedisClient
.create("redis://localhost:$port/")
val syncCommands = redisClient.connect().sync()
syncCommands.set("key", "value")
assertThat(syncCommands.get("key")).isEqualTo("value")
assertThat(embeddedRedisConfigurer.called).isTrue
}
}

@TestConfiguration
open class EmbeddedRedisConfigurerBeanTestConfiguration {
@Bean
open fun embeddedRedisConfigurer() = TestEmbeddedRedisConfigurerBean()
}

class TestEmbeddedRedisConfigurerBean : EmbeddedRedisConfigurer {
var called: Boolean = false

override fun configure(builder: RedisServerBuilder) {
called = true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.asarkar.spring.test.redis

import io.lettuce.core.RedisClient
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.test.context.SpringBootTest
import redis.embedded.RedisServerBuilder
import java.nio.file.Files
import java.nio.file.Paths
import kotlin.random.Random

private val charPool: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
private val file = Paths.get(AutoConfigureWithRandomPortsTest::class.java.getResource("/").toURI())
.let { testPath ->
generateSequence(testPath) {
if (Files.isDirectory(it) && Files.exists(it.resolve("build.gradle.kts"))) {
null
} else {
it.parent
}
}
.take(10) // should be plenty
.toList()
.last()
.resolve("build")
.resolve(
(1..6)
.map { Random.nextInt(0, charPool.size) }
.map(charPool::get)
.joinToString("")
)
}

@SpringBootTest
@AutoConfigureEmbeddedRedis(
port = 0,
serverConfigurerClass = "com.asarkar.spring.test.redis.TestEmbeddedRedisConfigurer"
)
class EmbeddedRedisConfigurerTest {
@Value("\${embedded-redis.port:-1}")
private var port: Int = -1

@Test
fun testEmbeddedRedisConfigurer() {
val redisClient = RedisClient
.create("redis://localhost:$port/")
val syncCommands = redisClient.connect().sync()
syncCommands.set("key", "value")
assertThat(syncCommands.get("key")).isEqualTo("value")
assertThat(Files.exists(file)).isTrue
}

@AfterEach
fun afterEach() {
Files.deleteIfExists(file)
}
}

class TestEmbeddedRedisConfigurer : EmbeddedRedisConfigurer {
private val log = LoggerFactory.getLogger(TestEmbeddedRedisConfigurer::class.java)

override fun configure(builder: RedisServerBuilder) {
Files.createFile(file)
.also { log.info("Created file: {}", it.toAbsolutePath()) }
}
}

0 comments on commit 37144f2

Please sign in to comment.