Skip to content

Commit 4e6435b

Browse files
committed
Fixes Issue #251
1 parent 39bde26 commit 4e6435b

File tree

3 files changed

+52
-3
lines changed

3 files changed

+52
-3
lines changed

common/src/main/scala/org/mockito/MockitoAPI.scala

+7-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import org.mockito.internal.creation.MockSettingsImpl
1818
import org.mockito.internal.exceptions.Reporter.notAMockPassedToVerifyNoMoreInteractions
1919
import org.mockito.internal.handler.ScalaMockHandler
2020
import org.mockito.internal.progress.ThreadSafeMockingProgress.mockingProgress
21+
import org.mockito.internal.stubbing.answers.ScalaThrowsException
2122
import org.mockito.internal.util.MockUtil
2223
import org.mockito.internal.util.reflection.LenientCopyTool
2324
import org.mockito.internal.{ ValueClassExtractor, ValueClassWrapper }
@@ -75,13 +76,17 @@ private[mockito] trait DoSomething {
7576
* Delegates to <code>Mockito.doThrow</code>, it's only here so we expose all the Mockito API
7677
* on a single place
7778
*/
78-
def doThrow(toBeThrown: Throwable*): Stubber = Mockito.doThrow(toBeThrown: _*)
79+
def doThrow(toBeThrown: Throwable*): Stubber = {
80+
val stubber = Mockito.MOCKITO_CORE.stubber
81+
toBeThrown.foreach(t => stubber.doAnswer(ScalaThrowsException(t)))
82+
stubber
83+
}
7984

8085
/**
8186
* Delegates to <code>Mockito.doThrow(type: Class[T])</code>
8287
* It provides a nicer API as you can, for instance, do doThrow[Throwable] instead of doThrow(classOf[Throwable])
8388
*/
84-
def doThrow[T <: Throwable: ClassTag]: Stubber = Mockito.doThrow(clazz)
89+
def doThrow[T <: Throwable: ClassTag]: Stubber = Mockito.doAnswer(ScalaThrowsException[T])
8590

8691
/**
8792
* Delegates to <code>Mockito.doNothing()</code>, it removes the parenthesis to have a cleaner API
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,19 @@
1-
package org.mockito.internal.stubbing.answers
1+
package org.mockito
2+
package internal.stubbing.answers
3+
4+
import org.mockito.internal.configuration.plugins.Plugins
25
import org.mockito.internal.exceptions.Reporter.cannotStubWithNullThrowable
36
import org.mockito.invocation.InvocationOnMock
47

8+
import scala.reflect.ClassTag
9+
510
class ScalaThrowsException(t: Throwable) extends ThrowsException(t) {
611
override def validateFor(invocation: InvocationOnMock): Unit = if (t == null) throw cannotStubWithNullThrowable
712
}
13+
14+
object ScalaThrowsException {
15+
def apply(t: Throwable): ScalaThrowsException = new ScalaThrowsException(t)
16+
17+
def apply[T <: Throwable: ClassTag]: ScalaThrowsException =
18+
new ScalaThrowsException(Plugins.getInstantiatorProvider.getInstantiator(null).newInstance(clazz))
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package user.org.mockito
2+
3+
import org.mockito.{ ArgumentMatchersSugar, IdiomaticMockito, MockitoSugar }
4+
import org.scalatest.flatspec.AnyFlatSpec
5+
import org.scalatest.matchers.should.Matchers
6+
7+
class Issue251 extends AnyFlatSpec with IdiomaticMockito with Matchers with ArgumentMatchersSugar {
8+
9+
case class Car(id: Int)
10+
class VehicleService {
11+
private var cars = Map.empty[Int, Car]
12+
cars += (0 -> Car(0))
13+
14+
def getCar(id: Int): Option[Car] = cars.get(id)
15+
def saveCar(car: Car) = {
16+
cars += car.id -> car;
17+
car
18+
}
19+
}
20+
21+
it should "allow to stub checked exceptions" in {
22+
val vehicleService = mock[VehicleService]
23+
val error = new Exception("A wild exception appears")
24+
error willBe thrown by vehicleService.getCar(any[Int])
25+
}
26+
27+
it should "allow to stub checked exceptions class" in {
28+
val vehicleService = mock[VehicleService]
29+
MockitoSugar.doThrow[Exception].when(vehicleService).getCar(any[Int])
30+
}
31+
32+
}

0 commit comments

Comments
 (0)