Skip to content

Commit 9ce9a4f

Browse files
authored
Merge pull request #48 from rcardin/30-add-assertions-to-understand-if-a-raisee-a-succeeded-of-failed
Added assertions to understand if a `Raise<E>.() -> A` succeeded of failed
2 parents 686bc27 + 7ccc11f commit 9ce9a4f

12 files changed

+227
-76
lines changed

src/main/kotlin/in/rcard/assertj/arrowcore/AbstractEitherAssert.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ import org.assertj.core.internal.StandardComparisonStrategy
2424
* @since 0.0.1
2525
*/
2626
abstract class AbstractEitherAssert<
27-
SELF : AbstractEitherAssert<SELF, LEFT, RIGHT>, LEFT : Any, RIGHT : Any,
28-
> internal constructor(
27+
SELF : AbstractEitherAssert<SELF, LEFT, RIGHT>,
28+
LEFT : Any,
29+
RIGHT : Any,
30+
> internal constructor(
2931
either: Either<LEFT, RIGHT>?,
3032
) : AbstractObjectAssert<SELF, Either<LEFT, RIGHT>>(either, AbstractEitherAssert::class.java) {
31-
3233
private val comparisonStrategy: ComparisonStrategy = StandardComparisonStrategy.instance()
3334

3435
/**

src/main/kotlin/in/rcard/assertj/arrowcore/AbstractRaiseAssert.kt

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ package `in`.rcard.assertj.arrowcore
22

33
import arrow.core.raise.Raise
44
import arrow.core.raise.fold
5-
import `in`.rcard.assertj.arrowcore.errors.RaiseShouldFailButSucceeded.Companion.shouldFailButSucceeded
5+
import `in`.rcard.assertj.arrowcore.errors.RaiseShouldFailButSucceeds.Companion.shouldFailButSucceedsWith
6+
import `in`.rcard.assertj.arrowcore.errors.RaiseShouldFailButSucceeds.Companion.shouldFailWithButSucceedsWith
67
import `in`.rcard.assertj.arrowcore.errors.RaiseShouldFailWith.Companion.shouldFailWith
78
import `in`.rcard.assertj.arrowcore.errors.RaiseShouldSucceedButFailed.Companion.shouldSucceedButFailed
89
import `in`.rcard.assertj.arrowcore.errors.RaiseShouldSucceedWith.Companion.shouldSucceedWith
10+
import `in`.rcard.assertj.arrowcore.errors.RaiseShouldSucceedWithButFailed.Companion.shouldSucceedWithButFailed
911
import org.assertj.core.api.AbstractAssert
1012
import org.assertj.core.internal.ComparisonStrategy
1113
import org.assertj.core.internal.StandardComparisonStrategy
@@ -19,10 +21,17 @@ import org.assertj.core.internal.StandardComparisonStrategy
1921
* @since 0.2.0
2022
*/
2123
abstract class AbstractRaiseAssert<
22-
SELF : AbstractRaiseAssert<SELF, ERROR, VALUE>, ERROR : Any, VALUE : Any,
23-
> internal constructor(lambda: context(Raise<ERROR>) () -> VALUE) :
24-
AbstractAssert<SELF, context(Raise<ERROR>) () -> VALUE>(lambda, AbstractRaiseAssert::class.java) {
25-
24+
SELF : AbstractRaiseAssert<SELF, ERROR, VALUE>,
25+
ERROR : Any,
26+
VALUE : Any,
27+
> internal constructor(
28+
lambda: context(Raise<ERROR>)
29+
() -> VALUE,
30+
) : AbstractAssert<
31+
SELF,
32+
context(Raise<ERROR>)
33+
() -> VALUE,
34+
>(lambda, AbstractRaiseAssert::class.java) {
2635
private val comparisonStrategy: ComparisonStrategy = StandardComparisonStrategy.instance()
2736

2837
/**
@@ -32,7 +41,14 @@ abstract class AbstractRaiseAssert<
3241
fun succeedsWith(expectedValue: VALUE) {
3342
fold(
3443
block = actual,
35-
recover = { actualError: ERROR -> throwAssertionError(shouldSucceedButFailed(expectedValue, actualError)) },
44+
recover = { actualError: ERROR ->
45+
throwAssertionError(
46+
shouldSucceedWithButFailed(
47+
expectedValue,
48+
actualError,
49+
),
50+
)
51+
},
3652
transform = { actualValue ->
3753
if (!comparisonStrategy.areEqual(actualValue, expectedValue)) {
3854
throwAssertionError(shouldSucceedWith(expectedValue, actualValue))
@@ -41,6 +57,20 @@ abstract class AbstractRaiseAssert<
4157
)
4258
}
4359

60+
/**
61+
* Verifies that the function in the [Raise] context succeeded. No check on the value returned by the function is
62+
* performed.
63+
*
64+
* @see succeedsWith
65+
*/
66+
fun succeeds() {
67+
fold(
68+
block = actual,
69+
recover = { actualError: ERROR -> throwAssertionError(shouldSucceedButFailed(actualError)) },
70+
transform = { _ -> },
71+
)
72+
}
73+
4474
/**
4575
* Verifies that the function in the [Raise] context fails with the given error.
4676
* @param expectedError the expected error raised by the function.
@@ -55,7 +85,24 @@ abstract class AbstractRaiseAssert<
5585
},
5686
transform = { actualValue ->
5787
throwAssertionError(
58-
shouldFailButSucceeded(expectedError, actualValue)
88+
shouldFailWithButSucceedsWith(expectedError, actualValue),
89+
)
90+
},
91+
)
92+
}
93+
94+
/**
95+
* Verifies that the function in the [Raise] context fails, no matter the type of the logical error.
96+
*
97+
* @see raises
98+
*/
99+
fun fails() {
100+
fold(
101+
block = actual,
102+
recover = { _ -> },
103+
transform = { actualValue ->
104+
throwAssertionError(
105+
shouldFailButSucceedsWith(actualValue),
59106
)
60107
},
61108
)

src/main/kotlin/in/rcard/assertj/arrowcore/errors/OptionShouldBePresent.kt

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,12 @@ import org.assertj.core.error.BasicErrorMessageFactory
1111
*/
1212
internal class OptionShouldBePresent private constructor() :
1313
BasicErrorMessageFactory("%nExpecting Option to contain a value but it didn't.") {
14-
companion object {
15-
16-
/**
17-
* Indicates that a value should be present in an empty [Option].
18-
*
19-
* @return a error message factory.
20-
*/
21-
internal fun shouldBePresent(): OptionShouldBePresent = OptionShouldBePresent()
14+
companion object {
15+
/**
16+
* Indicates that a value should be present in an empty [Option].
17+
*
18+
* @return a error message factory.
19+
*/
20+
internal fun shouldBePresent(): OptionShouldBePresent = OptionShouldBePresent()
21+
}
2222
}
23-
}

src/main/kotlin/in/rcard/assertj/arrowcore/errors/RaiseShouldFailButSucceeded.kt

Lines changed: 0 additions & 24 deletions
This file was deleted.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package `in`.rcard.assertj.arrowcore.errors
2+
3+
import org.assertj.core.error.BasicErrorMessageFactory
4+
5+
private const val SHOULD_FAIL_WITH_BUT_SUCCEEDS_WITH_MESSAGE: String =
6+
"%nExpecting the lambda to fail with:%n <%s> %nbut it succeeded with:%n <%s>"
7+
8+
private const val SHOULD_FAIL_BUT_SUCCEEDS_WITH_MESSAGE: String =
9+
"%nExpecting the lambda to fail<%s>, but it succeeded with:%n <%s>"
10+
11+
/**
12+
* Build error message when a lambda should fail with a logic error but it succeeded with a value.
13+
*
14+
* @author Riccardo Cardin
15+
* @since 0.2.0
16+
*/
17+
internal class RaiseShouldFailButSucceeds private constructor(
18+
expectedError: Any,
19+
actualSucceededValue: Any,
20+
message: String,
21+
) : BasicErrorMessageFactory(message, expectedError, actualSucceededValue) {
22+
companion object {
23+
internal fun shouldFailWithButSucceedsWith(
24+
expectedError: Any,
25+
actualSucceededValue: Any,
26+
): RaiseShouldFailButSucceeds =
27+
RaiseShouldFailButSucceeds(expectedError, actualSucceededValue, SHOULD_FAIL_WITH_BUT_SUCCEEDS_WITH_MESSAGE)
28+
29+
internal fun shouldFailButSucceedsWith(actualSucceededValue: Any): RaiseShouldFailButSucceeds =
30+
RaiseShouldFailButSucceeds("", actualSucceededValue, SHOULD_FAIL_BUT_SUCCEEDS_WITH_MESSAGE)
31+
}
32+
}

src/main/kotlin/in/rcard/assertj/arrowcore/errors/RaiseShouldSucceedButFailed.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@ package `in`.rcard.assertj.arrowcore.errors
33
import org.assertj.core.error.BasicErrorMessageFactory
44

55
private const val SHOULD_SUCCEED_BUT_FAILED_MESSAGE: String =
6-
"%nExpecting the lambda to succeed with:%n <%s> %nbut it failed with:%n <%s>"
6+
"%nExpecting the lambda to succeed but it failed with:%n <%s>"
77

88
/**
9-
* Build error message when a lambda should succeed but it fails with a logic error.
9+
* Build error message when a lambda should succeed, but it fails with a logic error.
1010
*
1111
* @author Riccardo Cardin
12-
* @since 0.2.0
12+
* @since 1.0.0
1313
*/
14-
internal class RaiseShouldSucceedButFailed private constructor(expected: Any, actualRaisedError: Any) :
15-
BasicErrorMessageFactory(SHOULD_SUCCEED_BUT_FAILED_MESSAGE, expected, actualRaisedError) {
16-
14+
internal class RaiseShouldSucceedButFailed private constructor(
15+
actualRaisedError: Any,
16+
) : BasicErrorMessageFactory(SHOULD_SUCCEED_BUT_FAILED_MESSAGE, actualRaisedError) {
1717
companion object {
18-
internal fun shouldSucceedButFailed(expected: Any, actualRaisedError: Any): RaiseShouldSucceedButFailed =
19-
RaiseShouldSucceedButFailed(expected, actualRaisedError)
18+
internal fun shouldSucceedButFailed(actualRaisedError: Any): RaiseShouldSucceedButFailed =
19+
RaiseShouldSucceedButFailed(actualRaisedError)
2020
}
2121
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package `in`.rcard.assertj.arrowcore.errors
2+
3+
import org.assertj.core.error.BasicErrorMessageFactory
4+
5+
private const val SHOULD_SUCCEED_WITH_BUT_FAILED_MESSAGE: String =
6+
"%nExpecting the lambda to succeed with:%n <%s> %nbut it failed with:%n <%s>"
7+
8+
/**
9+
* Build error message when a lambda should succeed with a value, but it fails with a logic error.
10+
*
11+
* @author Riccardo Cardin
12+
* @since 0.2.0
13+
*/
14+
internal class RaiseShouldSucceedWithButFailed private constructor(
15+
expected: Any,
16+
actualRaisedError: Any,
17+
) : BasicErrorMessageFactory(SHOULD_SUCCEED_WITH_BUT_FAILED_MESSAGE, expected, actualRaisedError) {
18+
companion object {
19+
internal fun shouldSucceedWithButFailed(
20+
expected: Any,
21+
actualRaisedError: Any,
22+
): RaiseShouldSucceedWithButFailed = RaiseShouldSucceedWithButFailed(expected, actualRaisedError)
23+
}
24+
}

src/test/kotlin/in/rcard/assertj/arrowcore/OptionAssert_assertThat_Test.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import org.assertj.core.api.BDDAssertions.then
66
import org.junit.jupiter.api.Test
77

88
internal class OptionAssert_assertThat_Test {
9-
109
@Test
1110
internal fun `should create an assertion instance when given object is not null`() {
1211
// GIVEN
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package `in`.rcard.assertj.arrowcore
2+
3+
import `in`.rcard.assertj.arrowcore.RaiseAssert.Companion.assertThat
4+
import `in`.rcard.assertj.arrowcore.errors.RaiseShouldFailButSucceeds.Companion.shouldFailButSucceedsWith
5+
import org.assertj.core.api.Assertions
6+
import org.junit.jupiter.api.Test
7+
8+
@Suppress("ktlint:standard:class-naming")
9+
internal class RaiseAssert_fails_Test {
10+
@Test
11+
internal fun `should pass if lambda raises a logical error`() {
12+
assertThat { Dummy.aFunctionThatRaisesAnError() }.fails()
13+
}
14+
15+
@Test
16+
internal fun `should fail if lambda succeeds with a value instead of failing`() {
17+
Assertions
18+
.assertThatThrownBy {
19+
assertThat { Dummy.aFunctionWithContext(42) }.fails()
20+
}.isInstanceOf(AssertionError::class.java)
21+
.hasMessage(
22+
shouldFailButSucceedsWith(42).create(),
23+
)
24+
}
25+
26+
@Test
27+
internal fun `should fail if lambda throws an exception`() {
28+
Assertions
29+
.assertThatThrownBy {
30+
assertThat { Dummy.aFunctionThatThrowsAnException() }.fails()
31+
}.isInstanceOf(RuntimeException::class.java)
32+
.hasMessage("AN EXCEPTION")
33+
}
34+
}
Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,43 @@
11
package `in`.rcard.assertj.arrowcore
22

33
import `in`.rcard.assertj.arrowcore.RaiseAssert.Companion.assertThat
4-
import `in`.rcard.assertj.arrowcore.errors.RaiseShouldFailButSucceeded.Companion.shouldFailButSucceeded
4+
import `in`.rcard.assertj.arrowcore.errors.RaiseShouldFailButSucceeds.Companion.shouldFailWithButSucceedsWith
55
import `in`.rcard.assertj.arrowcore.errors.RaiseShouldFailWith.Companion.shouldFailWith
66
import org.assertj.core.api.Assertions
77
import org.junit.jupiter.api.Test
88

99
internal class RaiseAssert_raises_Test {
10-
1110
@Test
1211
internal fun `should pass if lambda raises a logical error`() {
1312
assertThat { Dummy.aFunctionThatRaisesAnError() }.raises("LOGICAL ERROR")
1413
}
1514

1615
@Test
1716
internal fun `should fail if lambda raises a logical error different from the expected`() {
18-
Assertions.assertThatThrownBy {
19-
assertThat { Dummy.aFunctionThatRaisesAnError() }.raises("ANOTHER LOGICAL ERROR")
20-
}.isInstanceOf(AssertionError::class.java)
17+
Assertions
18+
.assertThatThrownBy {
19+
assertThat { Dummy.aFunctionThatRaisesAnError() }.raises("ANOTHER LOGICAL ERROR")
20+
}.isInstanceOf(AssertionError::class.java)
2121
.hasMessage(shouldFailWith("ANOTHER LOGICAL ERROR", "LOGICAL ERROR").create())
2222
}
2323

2424
@Test
2525
internal fun `should fail if lambda succeeds with a value instead of failing`() {
26-
Assertions.assertThatThrownBy {
27-
assertThat { Dummy.aFunctionWithContext(42) }.raises("LOGICAL ERROR")
28-
}.isInstanceOf(AssertionError::class.java)
26+
Assertions
27+
.assertThatThrownBy {
28+
assertThat { Dummy.aFunctionWithContext(42) }.raises("LOGICAL ERROR")
29+
}.isInstanceOf(AssertionError::class.java)
2930
.hasMessage(
30-
shouldFailButSucceeded("LOGICAL ERROR", 42).create(),
31+
shouldFailWithButSucceedsWith("LOGICAL ERROR", 42).create(),
3132
)
3233
}
3334

3435
@Test
3536
internal fun `should fail if lambda throws an exception`() {
36-
Assertions.assertThatThrownBy {
37-
assertThat { Dummy.aFunctionThatThrowsAnException() }.raises("LOGICAL ERROR")
38-
}.isInstanceOf(RuntimeException::class.java)
37+
Assertions
38+
.assertThatThrownBy {
39+
assertThat { Dummy.aFunctionThatThrowsAnException() }.raises("LOGICAL ERROR")
40+
}.isInstanceOf(RuntimeException::class.java)
3941
.hasMessage("AN EXCEPTION")
4042
}
4143
}

0 commit comments

Comments
 (0)