Skip to content

Commit 4ebc6f7

Browse files
authored
Merge pull request #81 from jdsatlin/allow-nullable-either-contents
feat(80): Allow for asserting on Eithers containing null values within them
2 parents 7e3d8bf + 34be11a commit 4ebc6f7

15 files changed

+215
-17
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ import org.assertj.core.internal.StandardComparisonStrategy
2525
*/
2626
abstract class AbstractEitherAssert<
2727
SELF : AbstractEitherAssert<SELF, LEFT, RIGHT>,
28-
LEFT : Any,
29-
RIGHT : Any,
28+
LEFT : Any?,
29+
RIGHT : Any?,
3030
> internal constructor(
3131
either: Either<LEFT, RIGHT>?,
3232
) : AbstractObjectAssert<SELF, Either<LEFT, RIGHT>>(either, AbstractEitherAssert::class.java) {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ import arrow.core.Either
1010
* @author Riccardo Cardin
1111
* @since 0.0.1
1212
*/
13-
class EitherAssert<LEFT : Any, RIGHT : Any> private constructor(either: Either<LEFT, RIGHT>?) :
13+
class EitherAssert<LEFT : Any?, RIGHT : Any?> private constructor(either: Either<LEFT, RIGHT>?) :
1414
AbstractEitherAssert<EitherAssert<LEFT, RIGHT>, LEFT, RIGHT>(either) {
1515
companion object {
16-
fun <LEFT : Any, RIGHT : Any> assertThat(actual: Either<LEFT, RIGHT>?): EitherAssert<LEFT, RIGHT> =
16+
fun <LEFT : Any?, RIGHT : Any?> assertThat(actual: Either<LEFT, RIGHT>?): EitherAssert<LEFT, RIGHT> =
1717
EitherAssert(actual)
1818
}
1919
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import org.assertj.core.error.BasicErrorMessageFactory
99
* @author Riccardo Cardin
1010
* @since 0.0.1
1111
*/
12-
internal class EitherShouldContain private constructor(message: String, actual: Either<Any, Any>, expected: Any) :
12+
internal class EitherShouldContain private constructor(message: String, actual: Either<Any?, Any?>, expected: Any?) :
1313
BasicErrorMessageFactory(message, actual, expected) {
1414

1515
companion object {
@@ -28,7 +28,7 @@ internal class EitherShouldContain private constructor(message: String, actual:
2828
* @param RIGHT the type of the value contained in the [Either] on the right side.
2929
* @return an error message factory
3030
*/
31-
internal fun <LEFT : Any, RIGHT : Any> shouldContainOnRight(
31+
internal fun <LEFT : Any?, RIGHT : Any?> shouldContainOnRight(
3232
actual: Either<LEFT, RIGHT>,
3333
expectedValue: RIGHT,
3434
): EitherShouldContain = EitherShouldContain(
@@ -46,7 +46,7 @@ internal class EitherShouldContain private constructor(message: String, actual:
4646
* @param RIGHT the type of the value contained in the [Either] on the right side.
4747
* @return an error message factory
4848
*/
49-
internal fun <LEFT : Any, RIGHT : Any> shouldContainOnLeft(
49+
internal fun <LEFT : Any?, RIGHT : Any?> shouldContainOnLeft(
5050
actual: Either<LEFT, RIGHT>,
5151
expectedValue: RIGHT,
5252
): EitherShouldContain = EitherShouldContain(

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ internal class EitherShouldContainInstanceOf private constructor(message: String
3030
* @throws java.lang.NullPointerException if either is null.
3131
*/
3232
internal fun shouldContainOnRightInstanceOf(
33-
actual: Either<Any, Any>,
33+
actual: Either<Any?, Any?>,
3434
expectedClass: Class<*>,
3535
): EitherShouldContainInstanceOf =
3636
actual.fold(
@@ -47,14 +47,14 @@ internal class EitherShouldContainInstanceOf private constructor(message: String
4747
EXPECTING_TO_CONTAIN_DIFFERENT_INSTANCE.format(
4848
actual.javaClass.simpleName,
4949
expectedClass.name,
50-
rightValue.javaClass.name,
50+
rightValue?.javaClass?.name ?: "null",
5151
),
5252
)
5353
},
5454
)
5555

5656
internal fun shouldContainOnLeftInstanceOf(
57-
actual: Either<Any, Any>,
57+
actual: Either<Any?, Any?>,
5858
expectedClass: Class<*>,
5959
): EitherShouldContainInstanceOf =
6060
actual.fold(
@@ -63,7 +63,7 @@ internal class EitherShouldContainInstanceOf private constructor(message: String
6363
EXPECTING_TO_CONTAIN_DIFFERENT_INSTANCE.format(
6464
actual.javaClass.simpleName,
6565
expectedClass.name,
66-
leftValue.javaClass.name,
66+
leftValue?.javaClass?.name ?: "null",
6767
),
6868
)
6969
},

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ internal class EitherAssert_asLeft_Test {
1717
assertThat(actualLeftValue).asLeft().isEqualTo(42)
1818
}
1919

20+
@Test
21+
internal fun `should return a valid Object assert if the either contains a left-sided null`() {
22+
val actualLeftValue: Either<Int?, Nothing> = null.left()
23+
assertThat(actualLeftValue).asLeft().isEqualTo(null)
24+
}
25+
2026
@Test
2127
internal fun `should fail if the either contains a right-sided value`() {
2228
val actualRightValue: Either<Nothing, String> = "42".right()
@@ -26,7 +32,15 @@ internal class EitherAssert_asLeft_Test {
2632
}
2733

2834
@Test
29-
internal fun `should fail if the either is null`() {
35+
internal fun `should fail if the either contains a right-sided null`() {
36+
val actualRightValue: Either<Nothing, String?> = null.right()
37+
Assertions.assertThatThrownBy { assertThat(actualRightValue).asLeft() }
38+
.isInstanceOf(AssertionError::class.java)
39+
.hasMessage(shouldBeLeft(actualRightValue).create())
40+
}
41+
42+
@Test
43+
internal fun `should fail if the either itself is null`() {
3044
val actualLeftValue: Either<Int, Nothing>? = null
3145
Assertions.assertThatThrownBy { assertThat(actualLeftValue).asLeft() }
3246
.isInstanceOf(AssertionError::class.java)

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ internal class EitherAssert_asRight_Test {
1717
assertThat(actualRightValue).asRight().isEqualTo(42)
1818
}
1919

20+
@Test
21+
internal fun `should return a valid Object assert if either contains a right-sided null`() {
22+
val actualRightValue: Either<Nothing, Int?> = null.right()
23+
assertThat(actualRightValue).asRight().isEqualTo(null)
24+
}
25+
2026
@Test
2127
internal fun `should fail if the either contains a left-sided value`() {
2228
val actualLeftValue: Either<String, Nothing> = "42".left()
@@ -26,7 +32,15 @@ internal class EitherAssert_asRight_Test {
2632
}
2733

2834
@Test
29-
internal fun `should fail if the either is null`() {
35+
internal fun `should fail if either contains a left-sided null`() {
36+
val actualLeftValue: Either<String?, Nothing> = null.left()
37+
Assertions.assertThatThrownBy { assertThat(actualLeftValue).asRight() }
38+
.isInstanceOf(AssertionError::class.java)
39+
.hasMessage(shouldBeRight(actualLeftValue).create())
40+
}
41+
42+
@Test
43+
internal fun `should fail if the either itself is null`() {
3044
val actualRightValue: Either<Nothing, Int>? = null
3145
Assertions.assertThatThrownBy { assertThat(actualRightValue).asRight() }
3246
.isInstanceOf(AssertionError::class.java)

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,41 @@ internal class EitherAssert_containsOnLeftInstanceOf_Test {
3535
.hasMessage(shouldBeLeft(actual).create())
3636
}
3737

38+
@Test
39+
internal fun `should fail if either contains a right-sided null`() {
40+
val actual: Either<Any, String?> = null.right()
41+
Assertions.assertThatThrownBy {
42+
assertThat(actual).containsLeftInstanceOf(
43+
Any::class.java,
44+
)
45+
}
46+
.isInstanceOf(AssertionError::class.java)
47+
.hasMessage(shouldBeLeft(actual).create())
48+
}
49+
3850
@Test
3951
internal fun `should pass if either contains required type on left`() {
4052
val actual: Either<String, Nothing> = "something".left()
4153
assertThat(actual)
4254
.containsLeftInstanceOf(String::class.java)
4355
}
4456

57+
@Test
58+
internal fun `should fail if either contains null value for type on left`() {
59+
val actual: Either<String?, Nothing> = null.left()
60+
Assertions.assertThatThrownBy {
61+
assertThat(actual)
62+
.containsLeftInstanceOf(String::class.java)
63+
}
64+
.isInstanceOf(AssertionError::class.java)
65+
.hasMessage(
66+
shouldContainOnLeftInstanceOf(
67+
actual,
68+
String::class.java
69+
).create()
70+
)
71+
}
72+
4573
@Test
4674
internal fun `should pass if either contains required type subclass on left`() {
4775
val actual = Child().left()

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ internal class EitherAssert_containsOnLeft_Test {
2828
EitherAssert.assertThat(leftValue).containsOnLeft("something")
2929
}
3030

31+
@Test
32+
internal fun `should pass if either contains an expected null on left side`() {
33+
val leftValue = null.left()
34+
EitherAssert.assertThat(leftValue).containsOnLeft(null)
35+
}
36+
3137
@Test
3238
internal fun `should fail if either does not contain expected value on left side`() {
3339
val actual: Either<String, Nothing> = "something".left()
@@ -41,6 +47,19 @@ internal class EitherAssert_containsOnLeft_Test {
4147
.hasMessage(shouldContainOnLeft(actual, expectedValue).create())
4248
}
4349

50+
@Test
51+
internal fun `should fail with informative error message if null is contained on left side and a value was expected`() {
52+
val actual: Either<String?, Nothing> = null.left()
53+
val expectedValue = "something"
54+
Assertions.assertThatThrownBy {
55+
EitherAssert.assertThat(actual).containsOnLeft(
56+
expectedValue,
57+
)
58+
}
59+
.isInstanceOf(AssertionError::class.java)
60+
.hasMessage(shouldContainOnLeft(actual, expectedValue).create())
61+
}
62+
4463
@Test
4564
internal fun `should fail if either is right`() {
4665
val actual: Either<String, String> = "nothing".right()
@@ -53,4 +72,17 @@ internal class EitherAssert_containsOnLeft_Test {
5372
.isInstanceOf(AssertionError::class.java)
5473
.hasMessage(shouldBeLeft(actual).create())
5574
}
75+
76+
@Test
77+
internal fun `should fail if either right-sided value is null`() {
78+
val actual: Either<String, String?> = null.right()
79+
val expectedValue = "something"
80+
Assertions.assertThatThrownBy {
81+
EitherAssert.assertThat(actual).containsOnLeft(
82+
expectedValue,
83+
)
84+
}
85+
.isInstanceOf(AssertionError::class.java)
86+
.hasMessage(shouldBeLeft(actual).create())
87+
}
5688
}

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,34 @@ internal class EitherAssert_containsOnRightInstanceOf_Test {
4848
)
4949
}
5050

51+
@Test
52+
internal fun `should fail if either contains a left-sided null`() {
53+
val actual: Either<String?, Any> = null.left()
54+
Assertions.assertThatThrownBy {
55+
assertThat(actual).containsRightInstanceOf(
56+
Any::class.java,
57+
)
58+
}
59+
.isInstanceOf(AssertionError::class.java)
60+
.hasMessage(shouldBeRight(actual).create())
61+
}
62+
63+
@Test
64+
internal fun `should fail if either contains null value for type on right`() {
65+
val actual: Either<Nothing, String?> = null.right()
66+
Assertions.assertThatThrownBy {
67+
assertThat(actual)
68+
.containsRightInstanceOf(String::class.java)
69+
}
70+
.isInstanceOf(AssertionError::class.java)
71+
.hasMessage(
72+
shouldContainOnRightInstanceOf(
73+
actual,
74+
String::class.java
75+
).create()
76+
)
77+
}
78+
5179
@Test
5280
internal fun `should pass if either contains required type subclass on right`() {
5381
val actual = Child().right()

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

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import org.junit.jupiter.api.Test
1111

1212
internal class EitherAssert_containsOnRight_Test {
1313
@Test
14-
internal fun `should fail when either is null`() {
14+
internal fun `should fail when either itself is null`() {
1515
val rightValue: Either<Nothing, String>? = null
1616
Assertions.assertThatThrownBy {
1717
EitherAssert.assertThat(rightValue).containsOnRight(
@@ -28,6 +28,12 @@ internal class EitherAssert_containsOnRight_Test {
2828
EitherAssert.assertThat(rightValue).containsOnRight("something")
2929
}
3030

31+
@Test
32+
internal fun `should pass if either contains a null on right side`() {
33+
val rightValue = null.right()
34+
EitherAssert.assertThat(rightValue).containsOnRight(null)
35+
}
36+
3137
@Test
3238
internal fun should_fail_if_either_is_left() {
3339
val actual: Either<String, String> = "nothing".left()
@@ -39,6 +45,17 @@ internal class EitherAssert_containsOnRight_Test {
3945
.hasMessage(shouldBeRight(actual).create())
4046
}
4147

48+
@Test
49+
internal fun `should fail if either contains a left sided null`() {
50+
val actual: Either<String?, String> = null.left()
51+
val expectedValue = "something"
52+
Assertions.assertThatThrownBy {
53+
EitherAssert.assertThat(actual).containsOnRight(expectedValue)
54+
}
55+
.isInstanceOf(AssertionError::class.java)
56+
.hasMessage(shouldBeRight(actual).create())
57+
}
58+
4259
@Test
4360
internal fun `should fail if either does not contain expected value on right side`() {
4461
val actual: Either<Nothing, String> = "something".right()
@@ -49,4 +66,15 @@ internal class EitherAssert_containsOnRight_Test {
4966
.isInstanceOf(AssertionError::class.java)
5067
.hasMessage(shouldContainOnRight(actual, expectedValue).create())
5168
}
69+
70+
@Test
71+
internal fun `should fail with informative error message if either contains null on right but a value was expected`() {
72+
val actual: Either<Nothing, String?> = null.right()
73+
val expectedValue = "nothing"
74+
Assertions.assertThatThrownBy {
75+
EitherAssert.assertThat(actual).containsOnRight(expectedValue)
76+
}
77+
.isInstanceOf(AssertionError::class.java)
78+
.hasMessage(shouldContainOnRight(actual, expectedValue).create())
79+
}
5280
}

0 commit comments

Comments
 (0)