Skip to content

Commit 9d5b0f8

Browse files
committed
Fix handling of Result type in synchronous functions
1 parent 1ea25bb commit 9d5b0f8

File tree

3 files changed

+318
-1
lines changed

3 files changed

+318
-1
lines changed

mockito-kotlin/src/main/kotlin/org/mockito/kotlin/internal/CoroutineAwareAnswer.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ internal class CoroutineAwareAnswer<T> private constructor(private val delegate:
6262
}
6363

6464
private fun Any.conditionallyUnboxAnswer(invokedKotlinFunction: KFunction<*>?): Any? {
65-
if (invokedKotlinFunction == null || !invokedKotlinFunction.isSuspend) return this
65+
if (invokedKotlinFunction == null) return this
6666

6767
val returnType = invokedKotlinFunction.returnType.jvmErasure
6868

tests/src/test/kotlin/test/Classes.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ interface SynchronousFunctions {
161161

162162
fun nullableCharValueClassResult(): CharValueClass?
163163

164+
fun <T> resultResult(): Result<T>
165+
164166
fun functionArgument(function: () -> Unit)
165167

166168
fun suspendFunctionArgument(function: suspend () -> Unit)

tests/src/test/kotlin/test/OngoingStubbingTest.kt

Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package test
33
import com.nhaarman.expect.expect
44
import com.nhaarman.expect.expectErrorWithMessage
55
import kotlinx.coroutines.runBlocking
6+
import org.junit.Assert.assertEquals
67
import org.junit.Assume.assumeFalse
78
import org.junit.Test
89
import org.mockito.Mockito
@@ -453,4 +454,318 @@ class OngoingStubbingTest : TestBase() {
453454
mock<Open> { on { throwsNPE() } doReturn "result" }
454455
}
455456
}
457+
458+
@Test
459+
fun `should stub function call with doAnswer to return Result of integer`() {
460+
val successValue = 123
461+
val mock =
462+
mock<SynchronousFunctions> {
463+
on { resultResult<Int>() } doAnswer { Result.success(successValue) }
464+
}
465+
466+
val result = mock.resultResult<Int>()
467+
468+
expect(result.getOrNull()).toBe(successValue)
469+
}
470+
471+
@Test
472+
fun `should stub function call with doAnswer to return Result of nullable integer`() {
473+
val successValue = 123 as Int?
474+
val mock =
475+
mock<SynchronousFunctions> {
476+
on { resultResult<Int?>() } doAnswer { Result.success(successValue) }
477+
}
478+
479+
val result = mock.resultResult<Int?>()
480+
481+
assertEquals(result.getOrNull(), successValue)
482+
}
483+
484+
@Test
485+
fun `should stub function call with doAnswer to return Result of boolean`() {
486+
val successValue = true
487+
val mock =
488+
mock<SynchronousFunctions> {
489+
on { resultResult<Boolean>() } doAnswer { Result.success(successValue) }
490+
}
491+
492+
val result = mock.resultResult<Boolean>()
493+
494+
expect(result.getOrNull()).toBe(successValue)
495+
}
496+
497+
@Test
498+
fun `should stub function call with doAnswer to return Result of nullable boolean`() {
499+
val successValue = true
500+
val mock =
501+
mock<SynchronousFunctions> {
502+
val nullableResult = Result.success(successValue as Boolean?)
503+
on { resultResult<Boolean?>() } doAnswer { nullableResult }
504+
}
505+
506+
val result = mock.resultResult<Boolean?>()
507+
508+
assertEquals(result.getOrNull(), successValue)
509+
}
510+
511+
@Test
512+
fun `should stub function call with doAnswer to return Result of value class`() {
513+
val successValue = ValueClass("test")
514+
val mock =
515+
mock<SynchronousFunctions> {
516+
on { resultResult<ValueClass>() } doAnswer { Result.success(successValue) }
517+
}
518+
519+
val result = mock.resultResult<ValueClass>()
520+
521+
expect(result.getOrNull()).toBe(successValue)
522+
}
523+
524+
@Test
525+
fun `should stub function call with doAnswer to return Result of nullable value class`() {
526+
val successValue = ValueClass("test") as ValueClass?
527+
val mock =
528+
mock<SynchronousFunctions> {
529+
on { resultResult<ValueClass?>() } doAnswer { Result.success(successValue) }
530+
}
531+
532+
val result = mock.resultResult<ValueClass?>()
533+
534+
assertEquals(result.getOrNull(), successValue)
535+
}
536+
537+
@Test
538+
fun `should stub function call with doAnswer to return Result of long value class`() {
539+
val successValue = LongValueClass(123)
540+
val mock =
541+
mock<SynchronousFunctions> {
542+
on { resultResult<LongValueClass>() } doAnswer { Result.success(successValue) }
543+
}
544+
545+
val result = mock.resultResult<LongValueClass>()
546+
547+
expect(result.getOrNull()).toBe(successValue)
548+
}
549+
550+
@Test
551+
fun `should stub function call with doAnswer to return Result of nullable long value class`() {
552+
val successValue = LongValueClass(123) as LongValueClass?
553+
val mock =
554+
mock<SynchronousFunctions> {
555+
on { resultResult<LongValueClass?>() } doAnswer { Result.success(successValue) }
556+
}
557+
558+
val result = mock.resultResult<LongValueClass?>()
559+
560+
assertEquals(result.getOrNull(), successValue)
561+
}
562+
563+
@Test
564+
fun `should stub function call with doAnswer to return Result of object`() {
565+
val successValue = Open()
566+
val mock =
567+
mock<SynchronousFunctions> {
568+
on { resultResult<Open>() } doAnswer { Result.success(successValue) }
569+
}
570+
571+
val result = mock.resultResult<Open>()
572+
573+
expect(result.getOrNull()).toBe(successValue)
574+
}
575+
576+
@Test
577+
fun `should stub function call with doAnswer to return Result of nullable object`() {
578+
val successValue = Open() as Open?
579+
val mock =
580+
mock<SynchronousFunctions> {
581+
on { resultResult<Open?>() } doAnswer { Result.success(successValue) }
582+
}
583+
584+
val result = mock.resultResult<Open?>()
585+
586+
assertEquals(result.getOrNull(), successValue)
587+
}
588+
589+
@Test
590+
fun `should stub function call with doAnswer to return Result with null value`() {
591+
val mock =
592+
mock<SynchronousFunctions> {
593+
on { resultResult<Int?>() } doAnswer { Result.success(null as Int?) }
594+
}
595+
596+
val result = mock.resultResult<Int?>()
597+
598+
expect(result.getOrNull()).toBeNull()
599+
}
600+
601+
@Test
602+
fun `should stub function call with doAnswer to return Result with failure`() {
603+
val exception = RuntimeException("deliberate")
604+
val mock =
605+
mock<SynchronousFunctions> {
606+
on { resultResult<Int>() } doAnswer { Result.failure(exception) }
607+
}
608+
609+
val result = mock.resultResult<Int>()
610+
611+
val actual = result.exceptionOrNull()
612+
expect(actual).toBe(exception)
613+
}
614+
615+
@Test
616+
fun `should stub function call with doReturn to return Result of integer`() {
617+
val successValue = 123
618+
val mock =
619+
mock<SynchronousFunctions> {
620+
on { resultResult<Int>() } doReturn Result.success(successValue)
621+
}
622+
623+
val result = mock.resultResult<Int>()
624+
625+
expect(result.getOrNull()).toBe(successValue)
626+
}
627+
628+
@Test
629+
fun `should stub function call with doReturn to return Result of nullable integer`() {
630+
val successValue = 123 as Int?
631+
val mock =
632+
mock<SynchronousFunctions> {
633+
on { resultResult<Int?>() } doReturn Result.success(successValue)
634+
}
635+
636+
val result = mock.resultResult<Int?>()
637+
638+
assertEquals(result.getOrNull(), successValue)
639+
}
640+
641+
@Test
642+
fun `should stub function call with doReturn to return Result of boolean`() {
643+
val successValue = true
644+
val mock =
645+
mock<SynchronousFunctions> {
646+
on { resultResult<Boolean>() } doReturn Result.success(successValue)
647+
}
648+
649+
val result = mock.resultResult<Boolean>()
650+
651+
expect(result.getOrNull()).toBe(successValue)
652+
}
653+
654+
@Test
655+
fun `should stub function call with doReturn to return Result of nullable boolean`() {
656+
val successValue = true
657+
val mock =
658+
mock<SynchronousFunctions> {
659+
val nullableResult = Result.success(successValue as Boolean?)
660+
on { resultResult<Boolean?>() } doReturn nullableResult
661+
}
662+
663+
val result = mock.resultResult<Boolean?>()
664+
665+
assertEquals(result.getOrNull(), successValue)
666+
}
667+
668+
@Test
669+
fun `should stub function call with doReturn to return Result of value class`() {
670+
val successValue = ValueClass("test")
671+
val mock =
672+
mock<SynchronousFunctions> {
673+
on { resultResult<ValueClass>() } doReturn Result.success(successValue)
674+
}
675+
676+
val result = mock.resultResult<ValueClass>()
677+
678+
expect(result.getOrNull()).toBe(successValue)
679+
}
680+
681+
@Test
682+
fun `should stub function call with doReturn to return Result of nullable value class`() {
683+
val successValue = ValueClass("test") as ValueClass?
684+
val mock =
685+
mock<SynchronousFunctions> {
686+
on { resultResult<ValueClass?>() } doReturn Result.success(successValue)
687+
}
688+
689+
val result = mock.resultResult<ValueClass?>()
690+
691+
assertEquals(result.getOrNull(), successValue)
692+
}
693+
694+
@Test
695+
fun `should stub function call with doReturn to return Result of long value class`() {
696+
val successValue = LongValueClass(123)
697+
val mock =
698+
mock<SynchronousFunctions> {
699+
on { resultResult<LongValueClass>() } doReturn Result.success(successValue)
700+
}
701+
702+
val result = mock.resultResult<LongValueClass>()
703+
704+
expect(result.getOrNull()).toBe(successValue)
705+
}
706+
707+
@Test
708+
fun `should stub function call with doReturn to return Result of nullable long value class`() {
709+
val successValue = LongValueClass(123) as LongValueClass?
710+
val mock =
711+
mock<SynchronousFunctions> {
712+
on { resultResult<LongValueClass?>() } doReturn Result.success(successValue)
713+
}
714+
715+
val result = mock.resultResult<LongValueClass?>()
716+
717+
assertEquals(result.getOrNull(), successValue)
718+
}
719+
720+
@Test
721+
fun `should stub function call with doReturn to return Result of object`() {
722+
val successValue = Open()
723+
val mock =
724+
mock<SynchronousFunctions> {
725+
on { resultResult<Open>() } doReturn Result.success(successValue)
726+
}
727+
728+
val result = mock.resultResult<Open>()
729+
730+
expect(result.getOrNull()).toBe(successValue)
731+
}
732+
733+
@Test
734+
fun `should stub function call with doReturn to return Result of nullable object`() {
735+
val successValue = Open() as Open?
736+
val mock =
737+
mock<SynchronousFunctions> {
738+
on { resultResult<Open?>() } doReturn Result.success(successValue)
739+
}
740+
741+
val result = mock.resultResult<Open?>()
742+
743+
assertEquals(result.getOrNull(), successValue)
744+
}
745+
746+
@Test
747+
fun `should stub function call with doReturn to return Result with null value`() {
748+
val mock =
749+
mock<SynchronousFunctions> {
750+
on { resultResult<Int?>() } doReturn Result.success(null as Int?)
751+
}
752+
753+
val result = mock.resultResult<Int?>()
754+
755+
expect(result.getOrNull()).toBeNull()
756+
}
757+
758+
@Test
759+
fun `should stub function call with doReturn to return Result with failure`() {
760+
val exception = RuntimeException("deliberate")
761+
val mock =
762+
mock<SynchronousFunctions> {
763+
on { resultResult<Int>() } doReturn Result.failure(exception)
764+
}
765+
766+
val result = mock.resultResult<Int>()
767+
768+
val actual = result.exceptionOrNull()
769+
expect(actual).toBe(exception)
770+
}
456771
}

0 commit comments

Comments
 (0)