Skip to content

Commit 3deda48

Browse files
authored
Merge pull request #23 from mockito/reset-mocks-after-each-test
Add trait that resets all mocks after each test
2 parents 7db8512 + c0825c3 commit 3deda48

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed

README.md

+20
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,26 @@ the mockito-scala API available in one go, i.e.
134134
class MyTest extends WordSpec with MockitoFixture
135135
```
136136

137+
## `org.mockito.integrations.scalatest.ResetMocksAfterEachTest`
138+
139+
Inspired by [this](https://stackoverflow.com/questions/51387234/is-there-a-per-test-non-specific-mock-reset-pattern-using-scalaplayspecmockito) StackOverflow question,
140+
mockito-scala provides this trait that helps to automatically reset any existent mock after each test is run
141+
The trait has to be mixed **after** `org.mockito.MockitoSugar` in order to work, otherwise your test will not compile
142+
The code shown in the StackOverflow question would look like this if using this mechanism
143+
144+
```scala
145+
TestClass extends PlaySpec with MockitoSugar with ResetMocksAfterEachTest
146+
147+
private val foo = mock[Foo]
148+
149+
override def fakeApplication(): Application = new GuiceApplicationBuilder().overrides(bind[Foo].toInstance(foo)).build
150+
```
151+
152+
The main advantage being we don't have to remember to reset each one of the mocks...
153+
154+
If for some reason we want to have a mock that is not reset automatically while using this trait, then it should be
155+
created via the companion object of `org.mockito.MockitoSugar` so is not tracked by this mechanism
156+
137157
## Experimental features
138158

139159
* **by-name** arguments is currently an experimental feature as the implementation is a bit hacky and it gave some people problems
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package org.mockito.integrations.scalatest
2+
3+
import java.util.concurrent.ConcurrentHashMap
4+
5+
import org.mockito.stubbing.Answer
6+
import org.mockito.{ MockCreator, MockSettings, MockitoSugar }
7+
import org.scalatest.{ Outcome, TestSuite }
8+
9+
import scala.reflect.ClassTag
10+
import scala.reflect.runtime.universe.TypeTag
11+
12+
trait ResetMocksAfterEachTest extends TestSuite with MockCreator { self: MockCreator =>
13+
14+
private val mocksToReset = ConcurrentHashMap.newKeySet[AnyRef]()
15+
16+
private def resetAll(): Unit = mocksToReset.forEach(MockitoSugar.reset(_))
17+
18+
override protected def withFixture(test: NoArgTest): Outcome = {
19+
val outcome = super.withFixture(test)
20+
resetAll()
21+
outcome
22+
}
23+
24+
private def addMock[T <: AnyRef](mock: T) = {
25+
mocksToReset.add(mock)
26+
mock
27+
}
28+
29+
abstract override def mock[T <: AnyRef: ClassTag: TypeTag]: T = addMock(super.mock[T])
30+
31+
abstract override def mock[T <: AnyRef: ClassTag: TypeTag](defaultAnswer: Answer[_]): T =
32+
addMock(super.mock[T](defaultAnswer))
33+
34+
abstract override def mock[T <: AnyRef: ClassTag: TypeTag](mockSettings: MockSettings): T =
35+
addMock(super.mock[T](mockSettings))
36+
37+
abstract override def mock[T <: AnyRef: ClassTag: TypeTag](name: String): T = addMock(super.mock[T](name))
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package org.mockito.integrations.scalatest
2+
3+
import org.mockito.MockitoSugar
4+
import org.scalatest.{Matchers, WordSpec}
5+
6+
class ResetMocksAfterEachTestTest extends WordSpec with MockitoSugar with ResetMocksAfterEachTest with Matchers {
7+
8+
trait Foo {
9+
def bar(a: String) = "bar"
10+
}
11+
12+
val foo = mock[Foo]
13+
14+
"ResetMocksAfterEachTest" should {
15+
16+
"have clean state for test 1" in {
17+
18+
verifyZeroInteractions(foo)
19+
20+
when(foo.bar("pepe")) thenReturn "mocked"
21+
22+
foo.bar("pepe") shouldBe "mocked"
23+
24+
}
25+
26+
"have clean state for test 2" in {
27+
28+
verifyZeroInteractions(foo)
29+
30+
when(foo.bar("pepe")) thenReturn "mocked2"
31+
32+
foo.bar("pepe") shouldBe "mocked2"
33+
34+
}
35+
36+
}
37+
38+
}

0 commit comments

Comments
 (0)