PageRenderTime 53ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/spring-data-mongodb/src/test/kotlin/org/springframework/data/mongodb/core/ReactiveFindOperationExtensionsTests.kt

http://github.com/SpringSource/spring-data-mongodb
Kotlin | 327 lines | 227 code | 81 blank | 19 comment | 0 complexity | 13e65c024a9a6ceebd039b680bba242b MD5 | raw file
  1. /*
  2. * Copyright 2017-2021 the original author or authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * https://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.springframework.data.mongodb.core
  17. import example.first.First
  18. import io.mockk.every
  19. import io.mockk.mockk
  20. import io.mockk.verify
  21. import kotlinx.coroutines.flow.take
  22. import kotlinx.coroutines.flow.toList
  23. import kotlinx.coroutines.runBlocking
  24. import org.assertj.core.api.Assertions.assertThat
  25. import org.assertj.core.api.Assertions.assertThatExceptionOfType
  26. import org.junit.Test
  27. import org.springframework.data.geo.Distance
  28. import org.springframework.data.geo.GeoResult
  29. import reactor.core.publisher.Flux
  30. import reactor.core.publisher.Mono
  31. /**
  32. * @author Mark Paluch
  33. * @author Sebastien Deleuze
  34. */
  35. class ReactiveFindOperationExtensionsTests {
  36. val operation = mockk<ReactiveFindOperation>(relaxed = true)
  37. val operationWithProjection = mockk<ReactiveFindOperation.FindWithProjection<First>>(relaxed = true)
  38. val distinctWithProjection = mockk<ReactiveFindOperation.DistinctWithProjection>(relaxed = true)
  39. val findDistinct = mockk<ReactiveFindOperation.FindDistinct>(relaxed = true)
  40. val reactiveFind = mockk<ReactiveFindOperation.ReactiveFind<KotlinUser>>(relaxed = true)
  41. @Test // DATAMONGO-1719
  42. @Suppress("DEPRECATION")
  43. fun `ReactiveFind#query(KClass) extension should call its Java counterpart`() {
  44. operation.query(First::class)
  45. verify { operation.query(First::class.java) }
  46. }
  47. @Test // DATAMONGO-1719
  48. fun `ReactiveFind#query() with reified type parameter extension should call its Java counterpart`() {
  49. operation.query<First>()
  50. verify { operation.query(First::class.java) }
  51. }
  52. @Test // DATAMONGO-1719, DATAMONGO-2086
  53. @Suppress("DEPRECATION")
  54. fun `ReactiveFind#FindOperatorWithProjection#asType(KClass) extension should call its Java counterpart`() {
  55. operationWithProjection.asType(User::class)
  56. verify { operationWithProjection.`as`(User::class.java) }
  57. }
  58. @Test // DATAMONGO-1719, DATAMONGO-2086
  59. fun `ReactiveFind#FindOperatorWithProjection#asType() with reified type parameter extension should call its Java counterpart`() {
  60. operationWithProjection.asType<User>()
  61. verify { operationWithProjection.`as`(User::class.java) }
  62. }
  63. @Test // DATAMONGO-1761, DATAMONGO-2086
  64. @Suppress("DEPRECATION")
  65. fun `ReactiveFind#DistinctWithProjection#asType(KClass) extension should call its Java counterpart`() {
  66. distinctWithProjection.asType(User::class)
  67. verify { distinctWithProjection.`as`(User::class.java) }
  68. }
  69. @Test // DATAMONGO-2086
  70. fun `ReactiveFind#DistinctWithProjection#asType() with reified type parameter extension should call its Java counterpart`() {
  71. distinctWithProjection.asType<User>()
  72. verify { distinctWithProjection.`as`(User::class.java) }
  73. }
  74. @Test // DATAMONGO-2417
  75. fun `ReactiveFind#distrinct() using KProperty1 should call its Java counterpart`() {
  76. every { operation.query(KotlinUser::class.java) } returns reactiveFind
  77. operation.distinct(KotlinUser::username)
  78. verify {
  79. operation.query(KotlinUser::class.java)
  80. reactiveFind.distinct("username")
  81. }
  82. }
  83. @Test // DATAMONGO-2417
  84. fun `ReactiveFind#FindDistinct#field() using KProperty should call its Java counterpart`() {
  85. findDistinct.distinct(KotlinUser::username)
  86. verify { findDistinct.distinct("username") }
  87. }
  88. @Test // DATAMONGO-2209
  89. fun terminatingFindAwaitOneWithValue() {
  90. val find = mockk<ReactiveFindOperation.TerminatingFind<String>>()
  91. every { find.one() } returns Mono.just("foo")
  92. runBlocking {
  93. assertThat(find.awaitOne()).isEqualTo("foo")
  94. }
  95. verify {
  96. find.one()
  97. }
  98. }
  99. @Test // DATAMONGO-2247
  100. fun terminatingFindAwaitOneWithNull() {
  101. val find = mockk<ReactiveFindOperation.TerminatingFind<String>>()
  102. every { find.one() } returns Mono.empty()
  103. assertThatExceptionOfType(NoSuchElementException::class.java).isThrownBy {
  104. runBlocking { find.awaitOne() }
  105. }
  106. verify {
  107. find.one()
  108. }
  109. }
  110. @Test // DATAMONGO-2247
  111. fun terminatingFindAwaitOneOrNullWithValue() {
  112. val find = mockk<ReactiveFindOperation.TerminatingFind<String>>()
  113. every { find.one() } returns Mono.just("foo")
  114. runBlocking {
  115. assertThat(find.awaitOneOrNull()).isEqualTo("foo")
  116. }
  117. verify {
  118. find.one()
  119. }
  120. }
  121. @Test // DATAMONGO-2247
  122. fun terminatingFindAwaitOneOrNullWithNull() {
  123. val find = mockk<ReactiveFindOperation.TerminatingFind<String>>()
  124. every { find.one() } returns Mono.empty()
  125. runBlocking {
  126. assertThat(find.awaitOneOrNull()).isNull()
  127. }
  128. verify {
  129. find.one()
  130. }
  131. }
  132. @Test // DATAMONGO-2209
  133. fun terminatingFindAwaitFirstWithValue() {
  134. val find = mockk<ReactiveFindOperation.TerminatingFind<String>>()
  135. every { find.first() } returns Mono.just("foo")
  136. runBlocking {
  137. assertThat(find.awaitFirst()).isEqualTo("foo")
  138. }
  139. verify {
  140. find.first()
  141. }
  142. }
  143. @Test // DATAMONGO-2247
  144. fun terminatingFindAwaitFirstWithNull() {
  145. val find = mockk<ReactiveFindOperation.TerminatingFind<String>>()
  146. every { find.first() } returns Mono.empty()
  147. assertThatExceptionOfType(NoSuchElementException::class.java).isThrownBy {
  148. runBlocking { find.awaitFirst() }
  149. }
  150. verify {
  151. find.first()
  152. }
  153. }
  154. @Test // DATAMONGO-2247
  155. fun terminatingFindAwaitFirstOrNullWithValue() {
  156. val find = mockk<ReactiveFindOperation.TerminatingFind<String>>()
  157. every { find.first() } returns Mono.just("foo")
  158. runBlocking {
  159. assertThat(find.awaitFirstOrNull()).isEqualTo("foo")
  160. }
  161. verify {
  162. find.first()
  163. }
  164. }
  165. @Test // DATAMONGO-2247
  166. fun terminatingFindAwaitFirstOrNullWithNull() {
  167. val find = mockk<ReactiveFindOperation.TerminatingFind<String>>()
  168. every { find.first() } returns Mono.empty()
  169. runBlocking {
  170. assertThat(find.awaitFirstOrNull()).isNull()
  171. }
  172. verify {
  173. find.first()
  174. }
  175. }
  176. @Test // DATAMONGO-2209
  177. fun terminatingFindAwaitCount() {
  178. val find = mockk<ReactiveFindOperation.TerminatingFind<String>>()
  179. every { find.count() } returns Mono.just(1)
  180. runBlocking {
  181. assertThat(find.awaitCount()).isEqualTo(1)
  182. }
  183. verify {
  184. find.count()
  185. }
  186. }
  187. @Test // DATAMONGO-2209
  188. fun terminatingFindAwaitExists() {
  189. val find = mockk<ReactiveFindOperation.TerminatingFind<String>>()
  190. every { find.exists() } returns Mono.just(true)
  191. runBlocking {
  192. assertThat(find.awaitExists()).isTrue()
  193. }
  194. verify {
  195. find.exists()
  196. }
  197. }
  198. @Test // DATAMONGO-2255
  199. fun terminatingFindAllAsFlow() {
  200. val spec = mockk<ReactiveFindOperation.TerminatingFind<String>>()
  201. every { spec.all() } returns Flux.just("foo", "bar", "baz")
  202. runBlocking {
  203. assertThat(spec.flow().toList()).contains("foo", "bar", "baz")
  204. }
  205. verify {
  206. spec.all()
  207. }
  208. }
  209. @Test // DATAMONGO-2255
  210. fun terminatingFindTailAsFlow() {
  211. val spec = mockk<ReactiveFindOperation.TerminatingFind<String>>()
  212. every { spec.tail() } returns Flux.just("foo", "bar", "baz").concatWith(Flux.never())
  213. runBlocking {
  214. assertThat(spec.tailAsFlow().take(3).toList()).contains("foo", "bar", "baz")
  215. }
  216. verify {
  217. spec.tail()
  218. }
  219. }
  220. @Test // DATAMONGO-2255
  221. fun terminatingFindNearAllAsFlow() {
  222. val spec = mockk<ReactiveFindOperation.TerminatingFindNear<String>>()
  223. val foo = GeoResult("foo", Distance(0.0))
  224. val bar = GeoResult("bar", Distance(0.0))
  225. val baz = GeoResult("baz", Distance(0.0))
  226. every { spec.all() } returns Flux.just(foo, bar, baz)
  227. runBlocking {
  228. assertThat(spec.flow().toList()).contains(foo, bar, baz)
  229. }
  230. verify {
  231. spec.all()
  232. }
  233. }
  234. @Test // DATAMONGO-2255
  235. fun terminatingDistinctAllAsFlow() {
  236. val spec = mockk<ReactiveFindOperation.TerminatingDistinct<String>>()
  237. every { spec.all() } returns Flux.just("foo", "bar", "baz")
  238. runBlocking {
  239. assertThat(spec.flow().toList()).contains("foo", "bar", "baz")
  240. }
  241. verify {
  242. spec.all()
  243. }
  244. }
  245. data class KotlinUser(val username: String)
  246. }