Skip to content

Commit

Permalink
Merge pull request #407 from FasterXML/run-failing-tests-always
Browse files Browse the repository at this point in the history
Always run failing tests, but make them pass
  • Loading branch information
dinomite committed Jan 4, 2021
2 parents 2840786 + 7adafb7 commit 160d99c
Show file tree
Hide file tree
Showing 18 changed files with 245 additions and 96 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,14 @@ If you are going to write code, choose the appropriate base branch:
- `2.12` for bugfixes against the current stable version
- `2.13` for additive functionality & features or [minor](https://semver.org), backwards compatible changes to existing behavior to be included in the next minor version release
- `master` for significant changes to existing behavior, which will be part of Jackson 3.0

### Failing tests

There are a number of tests for functionality that is broken, mostly in the [failing](https://github.com/FasterXML/jackson-module-kotlin/tree/master/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/failing)
package but a few as part of other test suites. Instead of ignoring these tests (with JUnit's `@Ignore` annotation)
or excluding them from being run as part of automated testing, the tests are written to demonstrate the failure
(either making a call that throws an exception or with an assertion that fails) but not fail the build, except if the
underlying issue is fixed. This allows us to know when the tested functionality has been incidentally fixed by
unrelated code changes.

See the [failing tests readme](https://github.com/FasterXML/jackson-module-kotlin/tree/master/src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/failing/README.md) for more information.
5 changes: 0 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,6 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>com/fasterxml/jackson/**/failing/*</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<!-- Inherited from oss-base. Generate PackageVersion.java.-->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,44 @@ import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.databind.annotation.JsonSerialize
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import org.hamcrest.CoreMatchers.equalTo
import org.hamcrest.MatcherAssert.assertThat
import org.junit.Ignore
import org.junit.Test

import kotlin.test.assertEquals

class TestIteratorSubclass {
class TinyPerson(val name: String, val age: Int)
class KotlinPersonIterator(private val personList: List<TinyPerson>) : Iterator<TinyPerson> by personList.iterator() {}
class KotlinPersonIterator(private val personList: List<TinyPerson>) : Iterator<TinyPerson> by personList.iterator()

val mapper: ObjectMapper = jacksonObjectMapper().configure(SerializationFeature.INDENT_OUTPUT, false)


@Test fun testKotlinIterator() {
@Test
fun testKotlinIteratorWithTypeRef() {
val expectedJson = """[{"name":"Fred","age":10},{"name":"Max","age":11}]"""
val people = KotlinPersonIterator(listOf(TinyPerson("Fred", 10), TinyPerson("Max", 11)))
val typeRef = object : TypeReference<Iterator<TinyPerson>>() {}
val kotlinJson = mapper.writerFor(typeRef).writeValueAsString(people)
assertThat(kotlinJson, equalTo(expectedJson))
assertEquals(expectedJson, kotlinJson)
}

@Ignore("Failing, but need change in Jackson to allow this to work.")
@Test fun testKotlinIteratorFails() {
@Test
fun testKotlinIterator() {
val expectedJson = """[{"name":"Fred","age":10},{"name":"Max","age":11}]"""
val people = KotlinPersonIterator(listOf(TinyPerson("Fred", 10), TinyPerson("Max", 11)))
val kotlinJson = mapper.writeValueAsString(people)
assertThat(kotlinJson, equalTo(expectedJson))
assertEquals(expectedJson, kotlinJson)
}

class Company(val name: String, @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") @JsonSerialize(`as` = java.util.Iterator::class) val people: KotlinPersonIterator)
class Company(
val name: String,
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") @JsonSerialize(`as` = java.util.Iterator::class) val people: KotlinPersonIterator
)

@Test fun testKotlinIteratorAsField() {
@Test
fun testKotlinIteratorAsField() {
val expectedJson = """{"name":"KidVille","people":[{"name":"Fred","age":10},{"name":"Max","age":11}]}"""
val people = KotlinPersonIterator(listOf(TinyPerson("Fred", 10), TinyPerson("Max", 11)))
val company = Company("KidVille", people)
val kotlinJson = mapper.writeValueAsString(company)
assertThat(kotlinJson, equalTo(expectedJson))
assertEquals(expectedJson, kotlinJson)
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.fasterxml.jackson.module.kotlin.test

import kotlin.test.fail

/**
* Expect a block to throw an exception. If a different type of exception is thrown or no
* exception is produced by the block, fail the test. In the latter case, no exception being
* thrown, fixMessage is printed.
*
* This function is intended to allow failing tests to be written and run as part of the build
* without causing it to fail, except if the failure is fixed, in which case the fixMessage
* should make it clear what has happened (i.e. that some previously broken functionality
* has been fixed).
*
* @param T The expected throwable
* @param fixMessage The message to print when the block succeeds
* @param block The block to execute
*/
inline fun <reified T : Throwable> expectFailure(
fixMessage: String,
block: () -> Unit
) {
try {
block()
} catch (e: Throwable) {
val throwableType = T::class
if (throwableType.isInstance(e)) {
// Expected exception, do nothing
} else {
fail("Expected $throwableType but got $e")
}

return
}

fail(fixMessage)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.fasterxml.jackson.module.kotlin.test

import org.junit.Assert.assertThrows
import org.junit.Test
import kotlin.test.assertEquals

class TestHelpersTest {
@Test
fun expectFailure_ExpectedExceptionThrown() {
expectFailure<AssertionError>("This will not be printed") {
throw AssertionError("This is expected")
}
}

@Test
fun expectFailure_AnotherExceptionThrown() {
val throwable = assertThrows(AssertionError::class.java) {
expectFailure<AssertionError>("This will not be printed") {
throw Exception("This is not expected")
}
}

assertEquals("Expected class java.lang.AssertionError but got java.lang.Exception: This is not expected", throwable.message)
}

@Test
fun expectFailure_NoExceptionThrown() {
val fixMessage = "Test will fail with this message"
val throwable = assertThrows(AssertionError::class.java) {
expectFailure<AssertionError>(fixMessage) {
// Do nothing
}
}

assertEquals(fixMessage, throwable.message)
}
}
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
package com.fasterxml.jackson.module.kotlin.test.github
package com.fasterxml.jackson.module.kotlin.test.failing

import com.fasterxml.jackson.annotation.JsonIgnoreProperties
import com.fasterxml.jackson.databind.exc.InvalidDefinitionException
import com.fasterxml.jackson.dataformat.xml.XmlMapper
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText
import com.fasterxml.jackson.module.kotlin.readValue
import com.fasterxml.jackson.module.kotlin.registerKotlinModule
import org.junit.Ignore
import com.fasterxml.jackson.module.kotlin.test.expectFailure
import org.junit.Test

class TestGithub138 {
@JacksonXmlRootElement(localName = "sms")
@JsonIgnoreProperties(ignoreUnknown = true)
data class Sms(
@JacksonXmlProperty(localName = "Phone", isAttribute = true)
val phone: String?,
@JacksonXmlProperty(localName = "Phone", isAttribute = true)
val phone: String?,

@JacksonXmlText
val text: String? = ""

)
@JacksonXmlText
val text: String? = ""
)

@Test
@Ignore("Not sure the cause of this yet...")
fun testDeserProblem() {
val xml = """<sms Phone="435242423412" Id="43234324">Lorem ipsum</sms>"""
val xmlMapper = XmlMapper().registerKotlinModule()
val sms = xmlMapper.readValue<Sms>(xml)

expectFailure<InvalidDefinitionException>("GitHub #138 has been fixed!") {
val jsms = xmlMapper.readValue<Sms>(xml)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
package com.fasterxml.jackson.module.kotlin.test.failing

import com.fasterxml.jackson.databind.MapperFeature
import com.fasterxml.jackson.databind.exc.MismatchedInputException
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import org.junit.Ignore
import com.fasterxml.jackson.module.kotlin.test.expectFailure
import org.junit.Test

class TestGithub160 {
data class DataClass(val blah: String)

@Test
// @Ignore("This error is caused by annotations being turned off, but in Jackson 2.x we cannot catch this uniformly across the board")
fun dataClass() {
val j = jacksonObjectMapper().configure(
MapperFeature.USE_ANNOTATIONS, false
)!!
j.readValue<DataClass>(""" {"blah":"blah"}""")
val mapper = jacksonObjectMapper().configure(MapperFeature.USE_ANNOTATIONS, false)
expectFailure<MismatchedInputException>("GitHub #160 has been fixed!") {
mapper.readValue<DataClass>("""{"blah":"blah"}""")
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.fasterxml.jackson.module.kotlin.test.failing

import com.fasterxml.jackson.annotation.JsonPropertyOrder
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.test.expectFailure
import org.junit.Test
import kotlin.test.assertEquals

Expand All @@ -16,6 +17,8 @@ class TestGithub271 {
val mapper = jacksonObjectMapper()

val json = mapper.writeValueAsString(Foo("a", "c"))
assertEquals("""{"a":"a","b":"b","c":"c"}""", json)
expectFailure<AssertionError>("GitHub #271 has been fixed!") {
assertEquals("""{"a":"a","b":"b","c":"c"}""", json)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo.As
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import com.fasterxml.jackson.module.kotlin.test.expectFailure
import org.junit.Test
import kotlin.test.assertNull

Expand All @@ -29,7 +30,9 @@ class Github335Test {
val json = mapper.writeValueAsString(oldEntity)
val newEntity = mapper.readValue<MyEntity>(json)

// Returns false: "null" String instead of null
assertNull(newEntity.type)
expectFailure<AssertionError>("GitHub #335 has been fixed!") {
// newEntity.type is the string "null" instead of the null value
assertNull(newEntity.type)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.fasterxml.jackson.module.kotlin.test.failing

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException
import com.fasterxml.jackson.module.kotlin.KotlinModule
import com.fasterxml.jackson.module.kotlin.readValue
import com.fasterxml.jackson.module.kotlin.test.expectFailure
import org.junit.Test
import kotlin.test.assertEquals

Expand All @@ -19,8 +21,10 @@ class OwnerRequestTest {

@Test
fun testDeserHit340() {
val value: IsField = jackson.readValue(json)
assertEquals("Got a foo", value.foo)
expectFailure<UnrecognizedPropertyException>("GitHub #340 has been fixed!") {
val value: IsField = jackson.readValue(json)
assertEquals("Got a foo", value.foo)
}
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.fasterxml.jackson.module.kotlin.test.failing

import com.fasterxml.jackson.databind.exc.MismatchedInputException
import com.fasterxml.jackson.dataformat.xml.XmlMapper
import com.fasterxml.jackson.module.kotlin.registerKotlinModule
import com.fasterxml.jackson.module.kotlin.test.expectFailure
import kotlin.test.Test
import kotlin.test.assertEquals

Expand All @@ -15,9 +17,11 @@ class TestGithub396 {
val mapper = XmlMapper().registerKotlinModule()

val xml = "<product><stuff></stuff></product>"
val product: Product = mapper.readValue(xml, Product::class.java)
expectFailure<MismatchedInputException>("GitHub #396 has been fixed!") {
val product: Product = mapper.readValue(xml, Product::class.java)

assertEquals(Product(null), product)
assertEquals(Product(null), product)
}
}

private data class Stuff(val str: String?)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package com.fasterxml.jackson.module.kotlin.test.github
package com.fasterxml.jackson.module.kotlin.test.failing

import com.fasterxml.jackson.annotation.JsonUnwrapped
import com.fasterxml.jackson.databind.exc.InvalidDefinitionException
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import org.junit.Ignore
import com.fasterxml.jackson.module.kotlin.test.expectFailure
import org.junit.Test


class TestGithub50 {
data class Name(val firstName: String, val lastName: String)

Expand All @@ -15,11 +15,11 @@ class TestGithub50 {
val position: String
)


@Test
@Ignore("""Fails with: Cannot define Creator property "name" as `@JsonUnwrapped`""")
fun testGithub50UnwrappedError() {
val JSON = """{"firstName":"John","lastName":"Smith","position":"Manager"}"""
val obj: Employee = jacksonObjectMapper().readValue(JSON)
val json = """{"firstName":"John","lastName":"Smith","position":"Manager"}"""
expectFailure<InvalidDefinitionException>("GitHub #50 has been fixed!") {
val obj: Employee = jacksonObjectMapper().readValue(json)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package com.fasterxml.jackson.module.kotlin.test.github
package com.fasterxml.jackson.module.kotlin.test.failing

import com.fasterxml.jackson.annotation.JsonIdentityInfo
import com.fasterxml.jackson.annotation.ObjectIdGenerators
import com.fasterxml.jackson.module.kotlin.*
import org.junit.Ignore
import com.fasterxml.jackson.databind.deser.UnresolvedForwardReference
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import com.fasterxml.jackson.module.kotlin.test.expectFailure
import org.junit.Test

class TestGithub54 {
@Ignore("TODO: Fix this, Github #54")
@Test
fun testDeserWithIdentityInfo() {
val mapper = jacksonObjectMapper()
Expand All @@ -20,12 +21,15 @@ class TestGithub54 {
entity1.entity2 = entity2

val json = mapper.writeValueAsString(entity1)
mapper.readValue<Entity1>(json)
expectFailure<UnresolvedForwardReference>("GitHub #54 has been fixed!") {
mapper.readValue<Entity1>(json)
}

}
}

@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator::class)
data class Entity1(val name: String, var entity2: Entity2? = null, var parent: Entity1? = null)

@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator::class)
class Entity2(val name: String, var entity1: Entity1? = null)
class Entity2(val name: String, var entity1: Entity1? = null)
Loading

0 comments on commit 160d99c

Please sign in to comment.