Migrate detekt-rules-exceptions tests to JUnit (#4572)

* Migrate detekt-rules-exceptions tests to JUnit

* Improve nested test descriptions
This commit is contained in:
Matthew Haughton
2022-02-09 08:22:54 +11:00
committed by GitHub
parent 6734a9f852
commit 1b72d0082d
17 changed files with 408 additions and 246 deletions

View File

@@ -5,6 +5,5 @@ plugins {
dependencies {
compileOnly(projects.detektApi)
testImplementation(projects.detektTest)
testImplementation(libs.bundles.testImplementation)
testRuntimeOnly(libs.spek.runner)
testImplementation(libs.assertj)
}

View File

@@ -167,7 +167,8 @@ class SwallowedException(config: Config = Config.empty) : Rule(config) {
}
companion object {
internal val EXCEPTIONS_IGNORED_BY_DEFAULT = listOf(
@JvmStatic
val EXCEPTIONS_IGNORED_BY_DEFAULT = listOf(
"InterruptedException",
"MalformedURLException",
"NumberFormatException",

View File

@@ -5,25 +5,29 @@ import io.gitlab.arturbosch.detekt.test.TestConfig
import io.gitlab.arturbosch.detekt.test.compileAndLint
import io.gitlab.arturbosch.detekt.test.lint
import org.assertj.core.api.Assertions.assertThat
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
class ExceptionRaisedInUnexpectedLocationSpec : Spek({
val subject by memoized { ExceptionRaisedInUnexpectedLocation() }
class ExceptionRaisedInUnexpectedLocationSpec {
val subject = ExceptionRaisedInUnexpectedLocation()
describe("ExceptionRaisedInUnexpectedLocation rule") {
@Nested
inner class `ExceptionRaisedInUnexpectedLocation rule` {
it("reports methods raising an unexpected exception") {
@Test
fun `reports methods raising an unexpected exception`() {
val path = resourceAsPath("ExceptionRaisedInMethodsPositive.kt")
assertThat(subject.lint(path)).hasSize(5)
}
it("does not report methods raising no exception") {
@Test
fun `does not report methods raising no exception`() {
val path = resourceAsPath("ExceptionRaisedInMethodsNegative.kt")
assertThat(subject.lint(path)).isEmpty()
}
it("reports the configured method") {
@Test
fun `reports the configured method`() {
val config = TestConfig(mapOf("methodNames" to listOf("toDo", "todo2")))
val findings = ExceptionRaisedInUnexpectedLocation(config).compileAndLint(
"""
@@ -34,7 +38,8 @@ class ExceptionRaisedInUnexpectedLocationSpec : Spek({
assertThat(findings).hasSize(1)
}
it("reports the configured method with String") {
@Test
fun `reports the configured method with String`() {
val config = TestConfig(mapOf("methodNames" to "toDo,todo2"))
val findings = ExceptionRaisedInUnexpectedLocation(config).compileAndLint(
"""
@@ -45,4 +50,4 @@ class ExceptionRaisedInUnexpectedLocationSpec : Spek({
assertThat(findings).hasSize(1)
}
}
})
}

View File

@@ -1,22 +1,21 @@
package io.gitlab.arturbosch.detekt.rules.exceptions
import io.gitlab.arturbosch.detekt.rules.setupKotlinEnvironment
import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest
import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext
import org.assertj.core.api.Assertions.assertThat
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
class InstanceOfCheckForExceptionSpec : Spek({
setupKotlinEnvironment()
@KotlinCoreEnvironmentTest
class InstanceOfCheckForExceptionSpec(val env: KotlinCoreEnvironment) {
val subject = InstanceOfCheckForException()
val env: KotlinCoreEnvironment by memoized()
val subject by memoized { InstanceOfCheckForException() }
describe("InstanceOfCheckForException rule") {
it("has is and as checks") {
@Nested
inner class `InstanceOfCheckForException rule` {
@Test
fun `has is and as checks`() {
val code = """
fun x() {
try {
@@ -30,7 +29,8 @@ class InstanceOfCheckForExceptionSpec : Spek({
assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2)
}
it("has nested is and as checks") {
@Test
fun `has nested is and as checks`() {
val code = """
fun x() {
try {
@@ -44,7 +44,8 @@ class InstanceOfCheckForExceptionSpec : Spek({
assertThat(subject.compileAndLintWithContext(env, code)).hasSize(2)
}
it("has no instance of check") {
@Test
fun `has no instance of check`() {
val code = """
fun x() {
try {
@@ -60,7 +61,8 @@ class InstanceOfCheckForExceptionSpec : Spek({
assertThat(subject.compileAndLintWithContext(env, code)).isEmpty()
}
it("has no checks for the subtype of an exception") {
@Test
fun `has no checks for the subtype of an exception`() {
val code = """
interface I
@@ -75,4 +77,4 @@ class InstanceOfCheckForExceptionSpec : Spek({
assertThat(subject.compileAndLintWithContext(env, code)).isEmpty()
}
}
})
}

View File

@@ -2,15 +2,17 @@ package io.gitlab.arturbosch.detekt.rules.exceptions
import io.gitlab.arturbosch.detekt.test.compileAndLint
import org.assertj.core.api.Assertions.assertThat
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
class NotImplementedDeclarationSpec : Spek({
val subject by memoized { NotImplementedDeclaration() }
class NotImplementedDeclarationSpec {
val subject = NotImplementedDeclaration()
describe("NotImplementedDeclaration rule") {
@Nested
inner class `NotImplementedDeclaration rule` {
it("reports NotImplementedErrors") {
@Test
fun `reports NotImplementedErrors`() {
val code = """
fun f() {
if (1 == 1) throw NotImplementedError()
@@ -19,7 +21,8 @@ class NotImplementedDeclarationSpec : Spek({
assertThat(subject.compileAndLint(code)).hasSize(2)
}
it("reports TODO method calls") {
@Test
fun `reports TODO method calls`() {
val code = """
fun f() {
TODO("not implemented")
@@ -28,7 +31,8 @@ class NotImplementedDeclarationSpec : Spek({
assertThat(subject.compileAndLint(code)).hasSize(2)
}
it("does not report TODO comments") {
@Test
fun `does not report TODO comments`() {
val code = """
fun f() {
// TODO
@@ -36,4 +40,4 @@ class NotImplementedDeclarationSpec : Spek({
assertThat(subject.compileAndLint(code)).isEmpty()
}
}
})
}

View File

@@ -1,21 +1,22 @@
package io.gitlab.arturbosch.detekt.rules.exceptions
import io.gitlab.arturbosch.detekt.rules.setupKotlinEnvironment
import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest
import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext
import org.assertj.core.api.Assertions.assertThat
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
class ObjectExtendsThrowableSpec : Spek({
setupKotlinEnvironment()
@KotlinCoreEnvironmentTest
class ObjectExtendsThrowableSpec(val env: KotlinCoreEnvironment) {
val subject by memoized { ObjectExtendsThrowable() }
val env: KotlinCoreEnvironment by memoized()
val subject = ObjectExtendsThrowable()
describe("ObjectExtendsThrowable rule") {
@Nested
inner class `ObjectExtendsThrowable rule` {
it("reports top-level objects that extend Throwable") {
@Test
fun `reports top-level objects that extend Throwable`() {
val code = """
object BanException : Throwable()
object AuthException : RuntimeException()
@@ -25,7 +26,8 @@ class ObjectExtendsThrowableSpec : Spek({
assertThat(subject.compileAndLintWithContext(env, code)).hasSize(4)
}
it("reports object subtype of sealed class that extends Throwable") {
@Test
fun `reports object subtype of sealed class that extends Throwable`() {
val code = """
sealed class DomainException : RuntimeException() {
data class Exception1(val prop1: String, val prop2: Boolean) : DomainException()
@@ -36,7 +38,8 @@ class ObjectExtendsThrowableSpec : Spek({
assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1)
}
it("reports object that extends custom exception") {
@Test
fun `reports object that extends custom exception`() {
val code = """
object ObjectCustomException : CustomException("singleton custom exception")
@@ -45,7 +48,8 @@ class ObjectExtendsThrowableSpec : Spek({
assertThat(subject.compileAndLintWithContext(env, code)).hasSize(1)
}
it("reports companion objects that extend Throwable") {
@Test
fun `reports companion objects that extend Throwable`() {
val code = """
class Test1 {
companion object : Throwable() {
@@ -74,7 +78,8 @@ class ObjectExtendsThrowableSpec : Spek({
assertThat(subject.compileAndLintWithContext(env, code)).hasSize(4)
}
it("does not report objects that do not extend Throwable") {
@Test
fun `does not report objects that do not extend Throwable`() {
val code = """
object BanException
object AuthException : CustomException(message = "Authentication failed!")
@@ -90,7 +95,8 @@ class ObjectExtendsThrowableSpec : Spek({
assertThat(subject.compileAndLintWithContext(env, code)).isEmpty()
}
it("does not report companion objects that do not extend Throwable") {
@Test
fun `does not report companion objects that do not extend Throwable`() {
val code = """
class Test1 {
companion object {
@@ -107,7 +113,8 @@ class ObjectExtendsThrowableSpec : Spek({
assertThat(subject.compileAndLintWithContext(env, code)).isEmpty()
}
it("does not report non-objects that do extend Throwable") {
@Test
fun `does not report non-objects that do extend Throwable`() {
val code = """
class BanException : Throwable()
data class AuthException(val code: Int) : RuntimeException()
@@ -126,7 +133,8 @@ class ObjectExtendsThrowableSpec : Spek({
assertThat(subject.compileAndLintWithContext(env, code)).isEmpty()
}
it("does not report an anonymous object that extends Throwable") {
@Test
fun `does not report an anonymous object that extends Throwable`() {
val code = """
val exception = object : AbstractCustomException() {}
@@ -135,4 +143,4 @@ class ObjectExtendsThrowableSpec : Spek({
assertThat(subject.compileAndLintWithContext(env, code)).isEmpty()
}
}
})
}

View File

@@ -2,17 +2,20 @@ package io.gitlab.arturbosch.detekt.rules.exceptions
import io.gitlab.arturbosch.detekt.test.compileAndLint
import org.assertj.core.api.Assertions.assertThat
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
class PrintStackTraceSpec : Spek({
val subject by memoized { PrintStackTrace() }
class PrintStackTraceSpec {
val subject = PrintStackTrace()
describe("PrintStackTrace") {
@Nested
inner class `print stack trace rule` {
context("catch clauses with printStacktrace methods") {
@Nested
inner class `catch clauses with printStacktrace methods` {
it("prints a stacktrace") {
@Test
fun `prints a stacktrace`() {
val code = """
fun x() {
try {
@@ -23,7 +26,8 @@ class PrintStackTraceSpec : Spek({
assertThat(subject.compileAndLint(code)).hasSize(1)
}
it("does not print a stacktrace") {
@Test
fun `does not print a stacktrace`() {
val code = """
fun x() {
try {
@@ -39,9 +43,11 @@ class PrintStackTraceSpec : Spek({
}
}
context("a stacktrace printed by a thread") {
@Nested
inner class `a stacktrace printed by a thread` {
it("prints one") {
@Test
fun `prints one`() {
val code = """
fun x() {
Thread.dumpStack()
@@ -53,4 +59,4 @@ class PrintStackTraceSpec : Spek({
}
}
}
})
}

View File

@@ -2,15 +2,17 @@ package io.gitlab.arturbosch.detekt.rules.exceptions
import io.gitlab.arturbosch.detekt.test.compileAndLint
import org.assertj.core.api.Assertions.assertThat
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
class RethrowCaughtExceptionSpec : Spek({
val subject by memoized { RethrowCaughtException() }
class RethrowCaughtExceptionSpec {
val subject = RethrowCaughtException()
describe("RethrowCaughtException rule") {
@Nested
inner class `RethrowCaughtException rule` {
it("reports when the same exception is rethrown") {
@Test
fun `reports when the same exception is rethrown`() {
val code = """
fun f() {
try {
@@ -22,7 +24,8 @@ class RethrowCaughtExceptionSpec : Spek({
assertThat(subject.compileAndLint(code)).hasSize(1)
}
it("does not report when the other exception is rethrown with same name") {
@Test
fun `does not report when the other exception is rethrown with same name`() {
val code = """
class A {
private lateinit var e: Exception
@@ -37,7 +40,8 @@ class RethrowCaughtExceptionSpec : Spek({
assertThat(subject.compileAndLint(code)).isEmpty()
}
it("reports when the same exception succeeded by dead code is rethrown") {
@Test
fun `reports when the same exception succeeded by dead code is rethrown`() {
val code = """
fun f() {
try {
@@ -50,7 +54,8 @@ class RethrowCaughtExceptionSpec : Spek({
assertThat(subject.compileAndLint(code)).hasSize(1)
}
it("reports when the same nested exception is rethrown") {
@Test
fun `reports when the same nested exception is rethrown`() {
val code = """
fun f() {
try {
@@ -65,7 +70,8 @@ class RethrowCaughtExceptionSpec : Spek({
assertThat(subject.compileAndLint(code)).hasSize(1)
}
it("does not report a wrapped exception") {
@Test
fun `does not report a wrapped exception`() {
val code = """
fun f() {
try {
@@ -77,7 +83,8 @@ class RethrowCaughtExceptionSpec : Spek({
assertThat(subject.compileAndLint(code)).isEmpty()
}
it("does not report wrapped exceptions") {
@Test
fun `does not report wrapped exceptions`() {
val code = """
fun f() {
try {
@@ -91,7 +98,8 @@ class RethrowCaughtExceptionSpec : Spek({
assertThat(subject.compileAndLint(code)).isEmpty()
}
it("does not report logged exceptions") {
@Test
fun `does not report logged exceptions`() {
val code = """
fun f() {
try {
@@ -106,7 +114,8 @@ class RethrowCaughtExceptionSpec : Spek({
assertThat(subject.compileAndLint(code)).isEmpty()
}
it("does not report when taking specific actions before throwing the exception") {
@Test
fun `does not report when taking specific actions before throwing the exception`() {
val code = """
fun f() {
try {
@@ -124,7 +133,8 @@ class RethrowCaughtExceptionSpec : Spek({
assertThat(subject.compileAndLint(code)).isEmpty()
}
it("does not report when exception rethrown only in first catch") {
@Test
fun `does not report when exception rethrown only in first catch`() {
val code = """
fun f() {
try {
@@ -138,7 +148,8 @@ class RethrowCaughtExceptionSpec : Spek({
assertThat(subject.compileAndLint(code)).isEmpty()
}
it("does not report when some work is done in last catch") {
@Test
fun `does not report when some work is done in last catch`() {
val code = """
fun f() {
try {
@@ -153,7 +164,8 @@ class RethrowCaughtExceptionSpec : Spek({
assertThat(subject.compileAndLint(code)).isEmpty()
}
it("does not report when there is no catch clauses") {
@Test
fun `does not report when there is no catch clauses`() {
val code = """
fun f() {
try {
@@ -164,7 +176,8 @@ class RethrowCaughtExceptionSpec : Spek({
assertThat(subject.compileAndLint(code)).isEmpty()
}
it("reports when exception rethrown in last catch") {
@Test
fun `reports when exception rethrown in last catch`() {
val code = """
fun f() {
try {
@@ -178,7 +191,8 @@ class RethrowCaughtExceptionSpec : Spek({
assertThat(subject.compileAndLint(code)).hasSize(1)
}
it("reports 2 violations for each catch") {
@Test
fun `reports 2 violations for each catch`() {
val code = """
fun f() {
try {
@@ -197,4 +211,4 @@ class RethrowCaughtExceptionSpec : Spek({
assertThat(result[1].startPosition.line == 7).isTrue
}
}
})
}

View File

@@ -1,22 +1,23 @@
package io.gitlab.arturbosch.detekt.rules.exceptions
import io.gitlab.arturbosch.detekt.rules.setupKotlinEnvironment
import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest
import io.gitlab.arturbosch.detekt.test.TestConfig
import io.gitlab.arturbosch.detekt.test.assertThat
import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
class ReturnFromFinallySpec : Spek({
setupKotlinEnvironment()
@KotlinCoreEnvironmentTest
class ReturnFromFinallySpec(val env: KotlinCoreEnvironment) {
val subject by memoized { ReturnFromFinally() }
val env: KotlinCoreEnvironment by memoized()
val subject = ReturnFromFinally()
describe("ReturnFromFinally rule") {
@Nested
inner class `ReturnFromFinally rule` {
context("a finally block with a return statement") {
@Nested
inner class `a finally block with a return statement` {
val code = """
fun x() {
try {
@@ -26,13 +27,15 @@ class ReturnFromFinallySpec : Spek({
}
"""
it("should report") {
@Test
fun `should report`() {
val findings = subject.compileAndLintWithContext(env, code)
assertThat(findings).hasSize(1)
}
}
context("a finally block with no return statement") {
@Nested
inner class `a finally block with no return statement` {
val code = """
fun x() {
try {
@@ -41,13 +44,15 @@ class ReturnFromFinallySpec : Spek({
}
"""
it("should not report") {
@Test
fun `should not report`() {
val findings = subject.compileAndLintWithContext(env, code)
assertThat(findings).isEmpty()
}
}
context("a finally block with a nested return statement") {
@Nested
inner class `a finally block with a nested return statement` {
val code = """
fun x() {
try {
@@ -59,13 +64,15 @@ class ReturnFromFinallySpec : Spek({
}
"""
it("should report") {
@Test
fun `should report`() {
val findings = subject.compileAndLintWithContext(env, code)
assertThat(findings).hasSize(1)
}
}
context("a finally block with a return in an inner function") {
@Nested
inner class `a finally block with a return in an inner function` {
val code = """
fun x() {
try {
@@ -78,13 +85,15 @@ class ReturnFromFinallySpec : Spek({
}
"""
it("should not report") {
@Test
fun `should not report`() {
val findings = subject.compileAndLintWithContext(env, code)
assertThat(findings).isEmpty()
}
}
context("a finally block with a return as labelled expression") {
@Nested
inner class `a finally block with a return as labelled expression` {
val code = """
fun x() {
label@{
@@ -95,20 +104,25 @@ class ReturnFromFinallySpec : Spek({
}
}
"""
it("should report when ignoreLabeled is false") {
@Test
fun `should report when ignoreLabeled is false`() {
val findings = subject.compileAndLintWithContext(env, code)
assertThat(findings).hasSize(1)
}
it("should not report when ignoreLabeled is true") {
@Test
fun `should not report when ignoreLabeled is true`() {
val config = TestConfig(mapOf("ignoreLabeled" to "true"))
val findings = ReturnFromFinally(config).compileAndLintWithContext(env, code)
assertThat(findings).isEmpty()
}
}
context("a finally block as expression for property") {
it("should report") {
@Nested
inner class `a finally block as expression for property` {
@Test
fun `should report`() {
val code = """
val expression = try {
"try"
@@ -125,8 +139,10 @@ class ReturnFromFinallySpec : Spek({
}
}
context("a finally block as expression for method") {
it("should report") {
@Nested
inner class `a finally block as expression for method` {
@Test
fun `should report`() {
val code = """
fun expression() = try {
"try"
@@ -143,8 +159,10 @@ class ReturnFromFinallySpec : Spek({
}
}
context("when a finally block called method that return value") {
it("should report") {
@Nested
inner class `when a finally block called method that return value` {
@Test
fun `should report`() {
val code = """
fun expression() = try {
"try"
@@ -163,8 +181,10 @@ class ReturnFromFinallySpec : Spek({
}
}
context("when finally block absents in expression for property") {
it("shouldn't report") {
@Nested
inner class `when finally block absents in expression for property` {
@Test
fun `shouldn't report`() {
val code = """
val expression = try {
"try"
@@ -179,9 +199,11 @@ class ReturnFromFinallySpec : Spek({
}
}
context("when finally block absents in expression for method") {
@Nested
inner class `when finally block absents in expression for method` {
it("shouldn't report") {
@Test
fun `shouldn't report`() {
val code = """
fun expression() = try {
"try"
@@ -196,8 +218,10 @@ class ReturnFromFinallySpec : Spek({
}
}
context("when try catch finally block is independent") {
it("shouldn't report") {
@Nested
inner class `when try catch finally block is independent` {
@Test
fun `shouldn't report`() {
val code = """
fun expression() {
try {
@@ -216,8 +240,10 @@ class ReturnFromFinallySpec : Spek({
}
}
context("when finally block doesn't contain return value") {
it("shouldn't report") {
@Nested
inner class `when finally block doesn't contain return value` {
@Test
fun `shouldn't report`() {
val code = """
val expression = try {
"try"
@@ -234,8 +260,10 @@ class ReturnFromFinallySpec : Spek({
}
}
context("when return value in finally block is property") {
it("should report") {
@Nested
inner class `when return value in finally block is property` {
@Test
fun `should report`() {
val code = """
val property: String = "property"
val expression = try {
@@ -254,4 +282,4 @@ class ReturnFromFinallySpec : Spek({
}
}
}
})
}

View File

@@ -3,15 +3,19 @@ package io.gitlab.arturbosch.detekt.rules.exceptions
import io.gitlab.arturbosch.detekt.test.TestConfig
import io.gitlab.arturbosch.detekt.test.compileAndLint
import org.assertj.core.api.Assertions.assertThat
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.MethodSource
class SwallowedExceptionSpec : Spek({
val subject by memoized { SwallowedException() }
class SwallowedExceptionSpec {
val subject = SwallowedException()
describe("SwallowedException rule") {
@Nested
inner class `SwallowedException rule` {
it("reports a swallowed exception") {
@Test
fun `reports a swallowed exception`() {
val code = """
fun f() {
try {
@@ -23,7 +27,8 @@ class SwallowedExceptionSpec : Spek({
assertThat(subject.compileAndLint(code)).hasSize(1)
}
it("reports swallowed exceptions only using exception strings") {
@Test
fun `reports swallowed exceptions only using exception strings`() {
val code = """
fun f() {
try {
@@ -37,7 +42,8 @@ class SwallowedExceptionSpec : Spek({
assertThat(subject.compileAndLint(code)).hasSize(2)
}
it("reports swallowed exceptions only using exception strings via variables") {
@Test
fun `reports swallowed exceptions only using exception strings via variables`() {
val code = """
fun f() {
try {
@@ -53,7 +59,8 @@ class SwallowedExceptionSpec : Spek({
assertThat(subject.compileAndLint(code)).hasSize(2)
}
it("reports swallowed exceptions only using exception strings via variables in 'if' block") {
@Test
fun `reports swallowed exceptions only using exception strings via variables in 'if' block`() {
val code = """
fun f() {
try {
@@ -73,7 +80,8 @@ class SwallowedExceptionSpec : Spek({
assertThat(subject.compileAndLint(code)).hasSize(2)
}
it("reports swallowed exceptions when it has multiple throw expressions") {
@Test
fun `reports swallowed exceptions when it has multiple throw expressions`() {
val code = """
fun f(condition: Boolean) {
try {
@@ -89,7 +97,8 @@ class SwallowedExceptionSpec : Spek({
assertThat(subject.compileAndLint(code)).hasSize(1)
}
it("reports swallowed exceptions when it has multiple throw expressions 2") {
@Test
fun `reports swallowed exceptions when it has multiple throw expressions 2`() {
val code = """
fun f(condition: Boolean) {
try {
@@ -105,7 +114,8 @@ class SwallowedExceptionSpec : Spek({
assertThat(subject.compileAndLint(code)).hasSize(1)
}
it("reports nested swallowed exceptions") {
@Test
fun `reports nested swallowed exceptions`() {
val code = """
fun f(condition: Boolean) {
try {
@@ -122,7 +132,8 @@ class SwallowedExceptionSpec : Spek({
assertThat(subject.compileAndLint(code)).hasSize(1)
}
it("reports a swallowed exception that is not logged") {
@Test
fun `reports a swallowed exception that is not logged`() {
val code = """
fun f() {
try {
@@ -134,15 +145,20 @@ class SwallowedExceptionSpec : Spek({
assertThat(subject.compileAndLint(code)).hasSize(1)
}
listOf(listOf("IllegalArgumentException"), "IllegalArgumentException").forEach { ignoredExceptionValue ->
context("ignores given exception types config") {
@Nested
inner class `when given listOf(IllegalArgumentException)` {
val ignoredExceptionValue = listOf("IllegalArgumentException")
val config by memoized {
@Nested
inner class `ignores given exception types config` {
val config =
TestConfig("ignoredExceptionTypes" to ignoredExceptionValue)
}
val rule by memoized { SwallowedException(config) }
it("ignores given exception type in configuration") {
val rule = SwallowedException(config)
@Test
fun `ignores given exception type in configuration`() {
val code = """
fun f() {
try {
@@ -153,7 +169,8 @@ class SwallowedExceptionSpec : Spek({
assertThat(rule.compileAndLint(code)).isEmpty()
}
it("reports exception type that is missing in the configuration") {
@Test
fun `reports exception type that is missing in the configuration`() {
val code = """
fun f() {
try {
@@ -166,12 +183,52 @@ class SwallowedExceptionSpec : Spek({
}
}
context("ignores given exception name config") {
@Nested
inner class `when given IllegalArgumentException` {
val ignoredExceptionValue = "IllegalArgumentException"
val config by memoized { TestConfig(mapOf("allowedExceptionNameRegex" to "myIgnore")) }
val rule by memoized { SwallowedException(config) }
@Nested
inner class `ignores given exception types config` {
it("ignores given exception name") {
val config =
TestConfig("ignoredExceptionTypes" to ignoredExceptionValue)
val rule = SwallowedException(config)
@Test
fun `ignores given exception type in configuration`() {
val code = """
fun f() {
try {
} catch (e: IllegalArgumentException) {
}
}
"""
assertThat(rule.compileAndLint(code)).isEmpty()
}
@Test
fun `reports exception type that is missing in the configuration`() {
val code = """
fun f() {
try {
} catch (e: Exception) {
}
}
"""
assertThat(rule.compileAndLint(code)).hasSize(1)
}
}
}
@Nested
inner class `ignores given exception name config` {
val config = TestConfig(mapOf("allowedExceptionNameRegex" to "myIgnore"))
val rule = SwallowedException(config)
@Test
fun `ignores given exception name`() {
val code = """
fun f() {
try {
@@ -182,7 +239,8 @@ class SwallowedExceptionSpec : Spek({
assertThat(rule.compileAndLint(code)).isEmpty()
}
it("reports exception name") {
@Test
fun `reports exception name`() {
val code = """
fun f() {
try {
@@ -194,7 +252,8 @@ class SwallowedExceptionSpec : Spek({
}
}
it("does not report wrapped exceptions") {
@Test
fun `does not report wrapped exceptions`() {
val code = """
fun f() {
try {
@@ -208,7 +267,8 @@ class SwallowedExceptionSpec : Spek({
assertThat(subject.compileAndLint(code)).isEmpty()
}
it("does not report used exception variables") {
@Test
fun `does not report used exception variables`() {
val code = """
fun f() {
try {
@@ -222,9 +282,10 @@ class SwallowedExceptionSpec : Spek({
assertThat(subject.compileAndLint(code)).isEmpty()
}
SwallowedException.EXCEPTIONS_IGNORED_BY_DEFAULT.forEach { exceptionName ->
it("ignores $exceptionName in the catch clause by default") {
val code = """
@ParameterizedTest(name = "ignores {0} in the catch clause by default")
@MethodSource("io.gitlab.arturbosch.detekt.rules.exceptions.SwallowedException#getEXCEPTIONS_IGNORED_BY_DEFAULT")
fun `ignores $exceptionName in the catch clause by default`(exceptionName: String) {
val code = """
import java.net.MalformedURLException
import java.text.ParseException
@@ -235,17 +296,19 @@ class SwallowedExceptionSpec : Spek({
}
}
"""
assertThat(subject.compileAndLint(code)).isEmpty()
assertThat(subject.compileAndLint(code)).isEmpty()
}
@ParameterizedTest(name = "ignores {0} in the catch body by default")
@MethodSource("io.gitlab.arturbosch.detekt.rules.exceptions.SwallowedException#getEXCEPTIONS_IGNORED_BY_DEFAULT")
fun `ignores $exceptionName in the catch body by default`(exceptionName: String) {
val exceptionInstantiation = if (exceptionName == "ParseException") {
"$exceptionName(\"\", 0)"
} else {
"$exceptionName(\"\")"
}
it("ignores $exceptionName in the catch body by default") {
val exceptionInstantiation = if (exceptionName == "ParseException") {
"$exceptionName(\"\", 0)"
} else {
"$exceptionName(\"\")"
}
val code = """
val code = """
import java.net.MalformedURLException
import java.text.ParseException
@@ -256,8 +319,7 @@ class SwallowedExceptionSpec : Spek({
}
}
"""
assertThat(subject.compileAndLint(code)).isEmpty()
}
assertThat(subject.compileAndLint(code)).isEmpty()
}
}
})
}

View File

@@ -2,15 +2,17 @@ package io.gitlab.arturbosch.detekt.rules.exceptions
import io.gitlab.arturbosch.detekt.test.compileAndLint
import org.assertj.core.api.Assertions.assertThat
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
class ThrowingExceptionFromFinallySpec : Spek({
val subject by memoized { ThrowingExceptionFromFinally() }
class ThrowingExceptionFromFinallySpec {
val subject = ThrowingExceptionFromFinally()
describe("ThrowingExceptionFromFinally rule") {
@Nested
inner class `ThrowingExceptionFromFinally rule` {
it("should report a throw expression") {
@Test
fun `should report a throw expression`() {
val code = """
fun x() {
try {
@@ -23,7 +25,8 @@ class ThrowingExceptionFromFinallySpec : Spek({
assertThat(subject.compileAndLint(code)).hasSize(1)
}
it("should report a nested throw expression") {
@Test
fun `should report a nested throw expression`() {
val code = """
fun x() {
try {
@@ -34,7 +37,8 @@ class ThrowingExceptionFromFinallySpec : Spek({
assertThat(subject.compileAndLint(code)).hasSize(1)
}
it("should not report a finally expression without a throw expression") {
@Test
fun `should not report a finally expression without a throw expression`() {
val code = """
fun x() {
try {
@@ -45,4 +49,4 @@ class ThrowingExceptionFromFinallySpec : Spek({
assertThat(subject.compileAndLint(code)).isEmpty()
}
}
})
}

View File

@@ -3,15 +3,17 @@ package io.gitlab.arturbosch.detekt.rules.exceptions
import io.gitlab.arturbosch.detekt.test.compileAndLint
import io.gitlab.arturbosch.detekt.test.lint
import org.assertj.core.api.Assertions.assertThat
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
class ThrowingExceptionInMainSpec : Spek({
val subject by memoized { ThrowingExceptionInMain() }
class ThrowingExceptionInMainSpec {
val subject = ThrowingExceptionInMain()
describe("ThrowingExceptionInMain rule") {
@Nested
inner class `ThrowingExceptionInMain rule` {
it("reports a runnable main function which throws an exception") {
@Test
fun `reports a runnable main function which throws an exception`() {
val code = """
fun main(args: Array<String>) { throw IllegalArgumentException() }
fun main(vararg args: String) { throw IllegalArgumentException() }
@@ -20,7 +22,8 @@ class ThrowingExceptionInMainSpec : Spek({
assertThat(subject.compileAndLint(code)).hasSize(3)
}
it("reports runnable main functions with @JvmStatic annotation which throw an exception") {
@Test
fun `reports runnable main functions with @JvmStatic annotation which throw an exception`() {
val code = """
class A {
companion object {
@@ -44,7 +47,8 @@ class ThrowingExceptionInMainSpec : Spek({
assertThat(subject.compileAndLint(code)).hasSize(3)
}
it("does not report top level main functions with a wrong signature") {
@Test
fun `does not report top level main functions with a wrong signature`() {
val code = """
private fun main(args: Array<String>) { throw IllegalArgumentException() }
private fun main() { throw IllegalArgumentException() }
@@ -54,7 +58,8 @@ class ThrowingExceptionInMainSpec : Spek({
assertThat(subject.lint(code)).isEmpty()
}
it("does not report top level main functions which throw no exception") {
@Test
fun `does not report top level main functions which throw no exception`() {
val code = """
fun main(args: Array<String>) { }
fun main() { }
@@ -63,7 +68,8 @@ class ThrowingExceptionInMainSpec : Spek({
assertThat(subject.compileAndLint(code)).isEmpty()
}
it("does not report top level main functions with expression body which throw no exception") {
@Test
fun `does not report top level main functions with expression body which throw no exception`() {
val code = """
fun main(args: Array<String>) = ""
fun main() = Unit
@@ -71,7 +77,8 @@ class ThrowingExceptionInMainSpec : Spek({
assertThat(subject.compileAndLint(code)).isEmpty()
}
it("does not report main functions with no @JvmStatic annotation inside a class") {
@Test
fun `does not report main functions with no @JvmStatic annotation inside a class`() {
val code = """
class A {
fun main(args: Array<String>) { throw IllegalArgumentException() }
@@ -84,4 +91,4 @@ class ThrowingExceptionInMainSpec : Spek({
assertThat(subject.compileAndLint(code)).isEmpty()
}
}
})
}

View File

@@ -3,19 +3,20 @@ package io.gitlab.arturbosch.detekt.rules.exceptions
import io.gitlab.arturbosch.detekt.test.TestConfig
import io.gitlab.arturbosch.detekt.test.compileAndLint
import org.assertj.core.api.Assertions.assertThat
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
class ThrowingExceptionsWithoutMessageOrCauseSpec : Spek({
val subject by memoized {
class ThrowingExceptionsWithoutMessageOrCauseSpec {
val subject =
ThrowingExceptionsWithoutMessageOrCause(
TestConfig("exceptions" to listOf("IllegalArgumentException"))
)
}
describe("ThrowingExceptionsWithoutMessageOrCause rule") {
@Nested
inner class `ThrowingExceptionsWithoutMessageOrCause rule` {
context("several exception calls") {
@Nested
inner class `several exception calls` {
val code = """
fun x() {
@@ -24,20 +25,24 @@ class ThrowingExceptionsWithoutMessageOrCauseSpec : Spek({
throw IllegalArgumentException()
}"""
it("reports calls to the default constructor") {
@Test
fun `reports calls to the default constructor`() {
assertThat(subject.compileAndLint(code)).hasSize(2)
}
it("does not report calls to the default constructor with empty configuration") {
@Test
fun `does not report calls to the default constructor with empty configuration`() {
val config = TestConfig("exceptions" to emptyList<String>())
val findings = ThrowingExceptionsWithoutMessageOrCause(config).compileAndLint(code)
assertThat(findings).isEmpty()
}
}
context("a test code which asserts an exception") {
@Nested
inner class `a test code which asserts an exception` {
it("does not report a call to this exception") {
@Test
fun `does not report a call to this exception`() {
val code = """
fun test() {
org.assertj.core.api.Assertions.assertThatIllegalArgumentException().isThrownBy { println() }
@@ -47,4 +52,4 @@ class ThrowingExceptionsWithoutMessageOrCauseSpec : Spek({
}
}
}
})
}

View File

@@ -2,15 +2,18 @@ package io.gitlab.arturbosch.detekt.rules.exceptions
import io.gitlab.arturbosch.detekt.test.compileAndLint
import org.assertj.core.api.Assertions.assertThat
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
class ThrowingNewInstanceOfSameExceptionSpec : Spek({
val subject by memoized { ThrowingNewInstanceOfSameException() }
class ThrowingNewInstanceOfSameExceptionSpec {
val subject = ThrowingNewInstanceOfSameException()
describe("ThrowingNewInstanceOfSameException rule") {
@Nested
inner class `ThrowingNewInstanceOfSameException rule` {
context("a catch block which rethrows a new instance of the caught exception") {
@Nested
inner class `a catch block which rethrows a new instance of the caught exception` {
val code = """
fun x() {
try {
@@ -20,13 +23,15 @@ class ThrowingNewInstanceOfSameExceptionSpec : Spek({
}
"""
it("should report") {
@Test
fun `should report`() {
val findings = subject.compileAndLint(code)
assertThat(findings).hasSize(1)
}
}
context("a catch block which rethrows a new instance of another exception") {
@Nested
inner class `a catch block which rethrows a new instance of another exception` {
val code = """
fun x() {
try {
@@ -36,13 +41,16 @@ class ThrowingNewInstanceOfSameExceptionSpec : Spek({
}
"""
it("should not report") {
@Test
fun `should not report`() {
val findings = subject.compileAndLint(code)
assertThat(findings).isEmpty()
}
}
context("a catch block which throws a new instance of the same exception type without wrapping the caught exception") {
@Nested
@DisplayName("a catch block which throws a new instance of the same exception type without wrapping the caught exception")
inner class CatchBlockThrowingSameExceptionWithoutWrapping {
val code = """
fun x() {
try {
@@ -52,10 +60,11 @@ class ThrowingNewInstanceOfSameExceptionSpec : Spek({
}
"""
it("should not report") {
@Test
fun `should not report`() {
val findings = subject.compileAndLint(code)
assertThat(findings).isEmpty()
}
}
}
})
}

View File

@@ -5,18 +5,20 @@ import io.gitlab.arturbosch.detekt.test.TestConfig
import io.gitlab.arturbosch.detekt.test.compileAndLint
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatExceptionOfType
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import java.util.regex.PatternSyntaxException
private const val CAUGHT_EXCEPTIONS_PROPERTY = "exceptionNames"
private const val ALLOWED_EXCEPTION_NAME_REGEX = "allowedExceptionNameRegex"
class TooGenericExceptionCaughtSpec : Spek({
class TooGenericExceptionCaughtSpec {
describe("a file with many caught exceptions") {
@Nested
inner class `a file with many caught exceptions` {
it("should find one of each kind of defaults") {
@Test
fun `should find one of each kind of defaults`() {
val rule = TooGenericExceptionCaught(Config.empty)
val findings = rule.compileAndLint(tooGenericExceptionCode)
@@ -25,7 +27,8 @@ class TooGenericExceptionCaughtSpec : Spek({
}
}
describe("a file with a caught exception which is ignored") {
@Nested
inner class `a file with a caught exception which is ignored` {
val code = """
class MyTooGenericException : RuntimeException()
@@ -39,7 +42,8 @@ class TooGenericExceptionCaughtSpec : Spek({
}
"""
it("should not report an ignored catch blocks because of its exception name") {
@Test
fun `should not report an ignored catch blocks because of its exception name`() {
val config = TestConfig(mapOf(ALLOWED_EXCEPTION_NAME_REGEX to "myIgnore"))
val rule = TooGenericExceptionCaught(config)
@@ -48,7 +52,8 @@ class TooGenericExceptionCaughtSpec : Spek({
assertThat(findings).isEmpty()
}
it("should not report an ignored catch blocks because of its exception type") {
@Test
fun `should not report an ignored catch blocks because of its exception type`() {
val config = TestConfig(mapOf(CAUGHT_EXCEPTIONS_PROPERTY to "[MyException]"))
val rule = TooGenericExceptionCaught(config)
@@ -57,7 +62,8 @@ class TooGenericExceptionCaughtSpec : Spek({
assertThat(findings).isEmpty()
}
it("should not fail when disabled with invalid regex on allowed exception names") {
@Test
fun `should not fail when disabled with invalid regex on allowed exception names`() {
val configRules = mapOf(
"active" to "false",
ALLOWED_EXCEPTION_NAME_REGEX to "*MyException"
@@ -69,7 +75,8 @@ class TooGenericExceptionCaughtSpec : Spek({
assertThat(findings).isEmpty()
}
it("should fail with invalid regex on allowed exception names") {
@Test
fun `should fail with invalid regex on allowed exception names`() {
val config = TestConfig(mapOf(ALLOWED_EXCEPTION_NAME_REGEX to "*Foo"))
val rule = TooGenericExceptionCaught(config)
assertThatExceptionOfType(PatternSyntaxException::class.java).isThrownBy {
@@ -77,4 +84,4 @@ class TooGenericExceptionCaughtSpec : Spek({
}
}
}
})
}

View File

@@ -3,14 +3,16 @@ package io.gitlab.arturbosch.detekt.rules.exceptions
import io.github.detekt.test.utils.compileContentForTest
import io.gitlab.arturbosch.detekt.test.yamlConfig
import org.assertj.core.api.Assertions.assertThat
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
class TooGenericExceptionSpec : Spek({
class TooGenericExceptionSpec {
describe("TooGenericException rule") {
@Nested
inner class `TooGenericException rule` {
it("should not report any as all catch exception rules are deactivated") {
@Test
fun `should not report any as all catch exception rules are deactivated`() {
val config = yamlConfig("deactivated-exceptions.yml")
val ruleSet = ExceptionsProvider().instance(config)
val file = compileContentForTest(tooGenericExceptionCode)
@@ -21,7 +23,7 @@ class TooGenericExceptionSpec : Spek({
assertThat(findings).isEmpty()
}
}
})
}
const val tooGenericExceptionCode = """
fun main() {

View File

@@ -3,34 +3,31 @@ package io.gitlab.arturbosch.detekt.rules.exceptions
import io.gitlab.arturbosch.detekt.test.TestConfig
import io.gitlab.arturbosch.detekt.test.compileAndLint
import org.assertj.core.api.Assertions.assertThat
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ValueSource
private const val EXCEPTION_NAMES = "exceptionNames"
private val tooGenericExceptions = listOf(
"Error",
"Exception",
"Throwable",
"RuntimeException"
)
class TooGenericExceptionThrownSpec {
class TooGenericExceptionThrownSpec : Spek({
@Nested
inner class `a file with many thrown exceptions` {
describe("a file with many thrown exceptions") {
@ParameterizedTest
@ValueSource(strings = ["Error", "Exception", "Throwable", "RuntimeException"])
fun `should report $exceptionName`(exceptionName: String) {
val config = TestConfig(mapOf(EXCEPTION_NAMES to "[$exceptionName]"))
val rule = TooGenericExceptionThrown(config)
tooGenericExceptions.forEach { exceptionName ->
it("should report $exceptionName") {
val config = TestConfig(mapOf(EXCEPTION_NAMES to "[$exceptionName]"))
val rule = TooGenericExceptionThrown(config)
val findings = rule.compileAndLint(tooGenericExceptionCode)
val findings = rule.compileAndLint(tooGenericExceptionCode)
assertThat(findings).hasSize(1)
}
assertThat(findings).hasSize(1)
}
it("should not report thrown exceptions") {
@Test
fun `should not report thrown exceptions`() {
val config = TestConfig(mapOf(EXCEPTION_NAMES to "['MyException', Bar]"))
val rule = TooGenericExceptionThrown(config)
@@ -39,7 +36,8 @@ class TooGenericExceptionThrownSpec : Spek({
assertThat(findings).isEmpty()
}
it("should not report caught exceptions") {
@Test
fun `should not report caught exceptions`() {
val config = TestConfig(mapOf(EXCEPTION_NAMES to "['Exception']"))
val rule = TooGenericExceptionThrown(config)
@@ -57,7 +55,8 @@ class TooGenericExceptionThrownSpec : Spek({
assertThat(findings).isEmpty()
}
it("should not report initialize exceptions") {
@Test
fun `should not report initialize exceptions`() {
val config = TestConfig(mapOf(EXCEPTION_NAMES to "['Exception']"))
val rule = TooGenericExceptionThrown(config)
@@ -67,4 +66,4 @@ class TooGenericExceptionThrownSpec : Spek({
assertThat(findings).isEmpty()
}
}
})
}