Skip to content

Commit 928bba1

Browse files
authored
Update index and key to take a lambda (#83)
* Update changelog * Update index and key to take a lambda This is to have better error messages when the collection does not have the given entry. It also better matches `isNotNull {}`.
1 parent e86445d commit 928bba1

File tree

5 files changed

+69
-31
lines changed

5 files changed

+69
-31
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ message.
1818
consistent and better mirrors `assertAll { ... }` which has a similar behavior.
1919
- New dependency on kotlin-reflect
2020
- `contains`, `doesNotContain`, and `each` works on Iterable instead of Collection
21+
- better error messages for collections
22+
- more display types in `show()` (Char, Byte, Long, Float, primitive Arrays)
23+
- Add `@DslMarker` to help catch misleading nested assertions.
2124

2225
### Breaking Changes
2326
- Because of the above, `Assert<Collection>.all` and `Assert<Array>.all` have both been renamed to `each`.

src/main/kotlin/assertk/assertions/any.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ fun <T : Any> Assert<T?>.isNull() {
236236
* ```
237237
* val name: String? = ...
238238
* assert(name).isNotNull() {
239-
* hasLength(4)
239+
* it.hasLength(4)
240240
* }
241241
* ```
242242
*/
Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
package assertk.assertions
22

33
import assertk.Assert
4+
import assertk.assertions.support.expected
5+
import assertk.assertions.support.fail
46
import assertk.assertions.support.show
57

68
/**
79
* Returns an assert that assertion on the value at the given index in the list.
810
*
911
* ```
10-
* assert(listOf(0, 1, 2)).index(1).isPositive()
12+
* assert(listOf(0, 1, 2)).index(1) { it.isPositive() }
1113
* ```
1214
*/
13-
fun <T> Assert<List<T>>.index(index: Int)
14-
= assert(actual[index], "${name ?: ""}${show(index, "[]")}")
15+
fun <T> Assert<List<T>>.index(index: Int, f: (Assert<T>) -> Unit) {
16+
if (index in 0 until actual.size) {
17+
f(assert(actual[index], "${name ?: ""}${show(index, "[]")}"))
18+
} else {
19+
expected("index to be in range:[0-${actual.size}) but was:${show(index)}")
20+
}
21+
}
1522

src/main/kotlin/assertk/assertions/map.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,13 @@ fun <K, V> Assert<Map<K, V>>.containsExactly(vararg elements: Pair<K, V>) {
9191
* Returns an assert that asserts on the value at the given key in the map.
9292
*
9393
* ```
94-
* assert(mapOf("key" to "value")).key("key").isEqualTo("value")
94+
* assert(mapOf("key" to "value")).key("key") { it.isEqualTo("value") }
9595
* ```
9696
*/
97-
fun <K, V> Assert<Map<K, V>>.key(key: K)
98-
= assert(actual.getValue(key), "${name ?: ""}${show(key, "[]")}")
97+
fun <K, V> Assert<Map<K, V>>.key(key: K, f: (Assert<V>) -> Unit) {
98+
if (key in actual) {
99+
f(assert(actual.getValue(key), "${name ?: ""}${show(key, "[]")}"))
100+
} else {
101+
expected("to have key:${show(key)}")
102+
}
103+
}

src/test/kotlin/test/assertk/LensAssertSpec.kt

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ class LensAssertSpec : Spek({
2424
it("should fail an unsuccessful test") {
2525
Assertions.assertThatThrownBy {
2626
assert(subject).prop("arg1") { it.arg1 }.isEqualTo("wrong")
27-
}.hasMessage("expected [arg1]:<\"[wrong]\"> but was:<\"[test]\"> (BasicDataObject(arg1=test, arg2=Nested(arg1=1)))")
27+
}
28+
.hasMessage("expected [arg1]:<\"[wrong]\"> but was:<\"[test]\"> (BasicDataObject(arg1=test, arg2=Nested(arg1=1)))")
2829
}
2930

3031
it("should pass a successful nested prop test") {
@@ -34,7 +35,8 @@ class LensAssertSpec : Spek({
3435
it("should fail an unsuccessful nested prop test") {
3536
Assertions.assertThatThrownBy {
3637
assert(subject).prop("arg2") { it.arg2 }.prop("arg1") { it.arg1 }.isEqualTo(0)
37-
}.hasMessage("expected [arg2.arg1]:<[0]> but was:<[1]> (BasicDataObject(arg1=test, arg2=Nested(arg1=1)))")
38+
}
39+
.hasMessage("expected [arg2.arg1]:<[0]> but was:<[1]> (BasicDataObject(arg1=test, arg2=Nested(arg1=1)))")
3840
}
3941
}
4042

@@ -46,7 +48,8 @@ class LensAssertSpec : Spek({
4648
it("should fail an unsuccessful test") {
4749
Assertions.assertThatThrownBy {
4850
assert(subject).prop(BasicDataObject::arg1).isEqualTo("wrong")
49-
}.hasMessage("expected [arg1]:<\"[wrong]\"> but was:<\"[test]\"> (BasicDataObject(arg1=test, arg2=Nested(arg1=1)))")
51+
}
52+
.hasMessage("expected [arg1]:<\"[wrong]\"> but was:<\"[test]\"> (BasicDataObject(arg1=test, arg2=Nested(arg1=1)))")
5053
}
5154

5255
it("should pass a successful nested prop test") {
@@ -56,7 +59,8 @@ class LensAssertSpec : Spek({
5659
it("should fail an unsuccessful nested prop test") {
5760
Assertions.assertThatThrownBy {
5861
assert(subject).prop(BasicDataObject::arg2).prop(Nested::arg1).isEqualTo(0)
59-
}.hasMessage("expected [arg2.arg1]:<[0]> but was:<[1]> (BasicDataObject(arg1=test, arg2=Nested(arg1=1)))")
62+
}
63+
.hasMessage("expected [arg2.arg1]:<[0]> but was:<[1]> (BasicDataObject(arg1=test, arg2=Nested(arg1=1)))")
6064
}
6165
}
6266
}
@@ -66,22 +70,28 @@ class LensAssertSpec : Spek({
6670

6771
on("index()") {
6872
it("should pass a successful test") {
69-
assert(subject, name = "subject").index(0).isEqualTo(listOf("one"))
73+
assert(subject, name = "subject").index(0) { it.isEqualTo(listOf("one")) }
7074
}
7175

7276
it("should fail an unsuccessful test") {
7377
Assertions.assertThatThrownBy {
74-
assert(subject, name = "subject").index(0).isEqualTo(listOf("wrong"))
78+
assert(subject, name = "subject").index(0) { it.isEqualTo(listOf("wrong")) }
7579
}.hasMessage("expected [subject[0]]:<[\"[wrong]\"]> but was:<[\"[one]\"]> ([[\"one\"], [\"two\"]])")
7680
}
7781

82+
it("should fail out of range") {
83+
Assertions.assertThatThrownBy {
84+
assert(subject, name = "subject").index(-1) { it.isEqualTo(listOf("one")) }
85+
}.hasMessage("expected [subject] index to be in range:[0-2) but was:<-1>")
86+
}
87+
7888
it("should pass a successful nested list test") {
79-
assert(subject).index(1).index(0).isEqualTo("two")
89+
assert(subject).index(1) { it.index(0) { it.isEqualTo("two") } }
8090
}
8191
8292
it("should fail an unsuccessful nested prop test") {
8393
Assertions.assertThatThrownBy {
84-
assert(subject, name = "subject").index(1).index(0).isEqualTo("wrong")
94+
assert(subject, name = "subject").index(1) { it.index(0) { it.isEqualTo("wrong") } }
8595
}.hasMessage("expected [subject[1][0]]:<\"[wrong]\"> but was:<\"[two]\"> ([[\"one\"], [\"two\"]])")
8696
}
8797
}
@@ -92,22 +102,30 @@ class LensAssertSpec : Spek({
92102

93103
on("key()") {
94104
it("should pass a successful test") {
95-
assert(subject, name = "subject").key("one").isEqualTo(mapOf("two" to 2))
105+
assert(subject, name = "subject").key("one") { it.isEqualTo(mapOf("two" to 2)) }
96106
}
97107

98108
it("should fail an unsuccessful test") {
99109
Assertions.assertThatThrownBy {
100-
assert(subject, name = "subject").key("one").isEqualTo(mapOf("wrong" to 2))
101-
}.hasMessage("expected [subject[\"one\"]]:<{\"[wrong]\"=2}> but was:<{\"[two]\"=2}> ({\"one\"={\"two\"=2}})")
110+
assert(subject, name = "subject").key("one") { it.isEqualTo(mapOf("wrong" to 2)) }
111+
}
112+
.hasMessage("expected [subject[\"one\"]]:<{\"[wrong]\"=2}> but was:<{\"[two]\"=2}> ({\"one\"={\"two\"=2}})")
113+
}
114+
115+
it("should fail with missing key") {
116+
Assertions.assertThatThrownBy {
117+
assert(subject, name = "subject").key("wrong") { it.isEqualTo(mapOf("two" to 2)) }
118+
}
119+
.hasMessage("expected [subject] to have key:<\"wrong\">")
102120
}
103121

104122
it("should pass a successful nested map test") {
105-
assert(subject).key("one").key("two").isEqualTo(2)
123+
assert(subject).key("one") { it.key("two") { it.isEqualTo(2) } }
106124
}
107125

108126
it("should fail an unsuccessful nested prop test") {
109127
Assertions.assertThatThrownBy {
110-
assert(subject, name = "subject").key("one").key("two").isEqualTo(0)
128+
assert(subject, name = "subject").key("one") { it.key("two") { it.isEqualTo(0) } }
111129
}.hasMessage("expected [subject[\"one\"][\"two\"]]:<[0]> but was:<[2]> ({\"one\"={\"two\"=2}})")
112130
}
113131
}
@@ -119,22 +137,27 @@ class LensAssertSpec : Spek({
119137
on("lookup") {
120138
it("should pass a successful test") {
121139
assert(subject, name = "subject")
122-
.key("key")
123-
.index(0)
124-
.prop(BasicDataObject::arg2)
125-
.prop(Nested::arg1)
126-
.isEqualTo(1)
140+
.key("key") {
141+
it.index(0) {
142+
it.prop(BasicDataObject::arg2)
143+
.prop(Nested::arg1)
144+
.isEqualTo(1)
145+
}
146+
}
127147
}
128148

129149
it("should fail an unsuccessful test") {
130150
Assertions.assertThatThrownBy {
131151
assert(subject, name = "subject")
132-
.key("key")
133-
.index(0)
134-
.prop(BasicDataObject::arg2)
135-
.prop(Nested::arg1)
136-
.isEqualTo(0)
137-
}.hasMessage("expected [subject[\"key\"][0].arg2.arg1]:<[0]> but was:<[1]> ({\"key\"=[BasicDataObject(arg1=test, arg2=Nested(arg1=1))]})")
152+
.key("key") {
153+
it.index(0) {
154+
it.prop(BasicDataObject::arg2)
155+
.prop(Nested::arg1)
156+
.isEqualTo(0)
157+
}
158+
}
159+
}
160+
.hasMessage("expected [subject[\"key\"][0].arg2.arg1]:<[0]> but was:<[1]> ({\"key\"=[BasicDataObject(arg1=test, arg2=Nested(arg1=1))]})")
138161
}
139162
}
140163
}

0 commit comments

Comments
 (0)