Skip to content

Instantly share code, notes, and snippets.

View dmcg's full-sized avatar
💭
Splendid

Duncan McGregor dmcg

💭
Splendid
View GitHub Profile
class PartitionTests3 : JUnit5Minutests {
data class Fixture(
val items: List<Int> = emptyList(),
val predicates: List<(Int) -> Boolean> = emptyList()
) {
fun assertResultIs(vararg expected: List<Int>) {
assertEquals(expected.asList(), items.partition(predicates))
}
fun withItems(vararg items: Int) = copy(items = items.asList())
class PartitionTests2 : JUnit5Minutests {
override val tests = rootContext<Unit> {
context("no items") {
context("no predicates") {
test("returns empty list") {
val list = emptyList<Int>()
val predicates = emptyList<(Int) -> Boolean>()
val result = list.partition(predicates)
assertEquals(emptyList<List<List<Int>>>(), result)
class PartitionTests : JUnit5Minutests {
override val tests = rootContext<Unit> {
test("empty input and predicates") {
val list = emptyList<Int>()
val predicates = emptyList<(Int) -> Boolean>()
val result = list.partition(predicates)
assertEquals(emptyList<List<List<Int>>>(), result)
}
test("empty input some predicates") {
@dmcg
dmcg / userOverrideProperties.kt
Created November 30, 2018 08:30
Konfig ConfigurationProperties from file that may not exist
fun userOverrideProperties(file: File): ConfigurationProperties =
if (file.isFile)
ConfigurationProperties.fromFile(file)
else
ConfigurationProperties(Properties(), Location(file.absolutePath, file.toURI()))
@dmcg
dmcg / dataCopy.kt
Created November 12, 2018 15:24
Copy a Kotlin data object, applying a transform to every field
@Suppress("UNCHECKED_CAST")
fun <T: Any> T.dataCopy(mapper: (Any?) -> Any?): T {
val memberFunctions = this::class.memberFunctions
val components = memberFunctions.filter { it.name.startsWith("component") }.sortedBy { it.name.substringAfter("component").toInt() }
val componentValues = components.map { it.call(this) }.toTypedArray()
val copyMethod: KFunction<*> = memberFunctions.first { it.name == "copy" }
val copyArgs: List<Any?> = listOf(this) + componentValues.map(mapper)
return copyMethod.call(*copyArgs.toTypedArray()) as T
}
@dmcg
dmcg / JUnitTestRuleMockery.kt
Created November 12, 2018 09:36
Kotlin JMock JUnit TestRule
/**
* A [TestRule] as opposed to [MethodRule], without the auto-population gubbins.
*/
class JUnitTestRuleMockery : JUnit4Mockery(), TestRule {
override fun apply(base: Statement, description: Description) = object : Statement() {
override fun evaluate() {
base.evaluate()
assertIsSatisfied()
}
}
@dmcg
dmcg / jmock.kt
Created September 13, 2018 16:18
JUnit 5 JMock extension
import org.jmock.integration.junit4.JUnit4Mockery
import org.junit.jupiter.api.extension.AfterEachCallback
import org.junit.jupiter.api.extension.ExtensionContext
class MockeryExtension : JUnit4Mockery(), AfterEachCallback {
override fun afterEach(context: ExtensionContext) {
assertIsSatisfied()
}
}
private class KotlinValidationConstraintResolver : AnnotationConstraintResolver() {
override fun getRequired(prop: BeanProperty): Boolean? = super.getRequired(prop) ?: isNullable(prop) == false
}
private fun isNullable(prop: BeanProperty): Boolean? = when (prop) {
is BeanPropertyWriter -> prop.isNullable()
else -> null
}
private fun BeanPropertyWriter.isNullable(): Boolean? {
@dmcg
dmcg / xml.kt
Created December 15, 2016 19:59
Kotlin XML builder
fun article(licenceCode: String) = elem("article") {
elem("front") {
elem("journal-meta") {
elem("journal-id", "journal-id-type" to "publisher") {
text(licenceCode)
}
}
}
elem("body")
}
@dmcg
dmcg / MockingTesting.kt
Created September 23, 2016 10:46
Typesafe JMock actions
class MockingTesting {
@Rule @JvmField val mockery = JUnitRuleMockery()
val charSequence = mockery.createMock<CharSequence>()
@Test fun `which will taking untyped Action`() {
mockery.expecting {
oneOf(charSequence).length.which will org.jmock.Expectations.returnValue(42)
oneOf(charSequence).length.which will org.jmock.Expectations.throwException(RuntimeException())
oneOf(charSequence).length.which will org.jmock.Expectations.returnValue("banana")