Reputation: 2931
Problem:
Let's say we have two different service
class ServiceA(serviceB: ServiceB) {
def methodA(): String = {
"methodA called"
serviceB.methodB()
}
def methodA2(): String = {
"methodA2 called"
serviceB.methodB()
}
}
I write two test method and try to verify methodB called or not. When I run two test cases separately, tests pass. When I run all test methods, verification gives wrong result for second test. In test class context, mockito-verification records all calls on mock object. I think mockito-scala should reset verification counts on mock objects after each test
class ServiceATest extends FlatSpec with IdiomaticMockito {
val serviceB: ServiceB = mock[ServiceB]
val serviceA: ServiceA = new ServiceA(serviceB)
"methodA" should "called" in {
serviceA.methodA()
serviceB.methodB wasCalled once // Passes
}
"methodA2" should "called" in {
serviceA.methodA2()
serviceB.methodB wasCalled once // Fail. was 2 times
}
}
Btw I tried with mockito-core, it gives same error.
Upvotes: 0
Views: 188
Reputation: 23788
Your serviceA
and serviceB
objects are effectively test fixtures but you share them in a wrong way. With a code like yours the same objects are shared by all of the tests and it means that the tests interact with each other via shared dirty state. ScalaTest support many ways to share fixtures. One of the cleaner ways is the loan pattern as in:
class ServiceATest extends FlatSpec with IdiomaticMockito {
def withServicesAandBMock(testCode: (ServiceA, ServiceB) => Any) {
val serviceB: ServiceB = mock[ServiceB]
val serviceA: ServiceA = new ServiceA(serviceB)
testCode(serviceA, serviceB)
}
"methodA" should "called" in withServicesAandBMock { (serviceA, serviceB) =>
serviceA.methodA()
serviceB.methodB wasCalled once // Passes
}
"methodA2" should "called" in withServicesAandBMock { (serviceA, serviceB) =>
serviceA.methodA2()
serviceB.methodB wasCalled once // now passes as well
}
}
Alternatively you may use ResetMocksAfterEachTest
class ServiceATest extends FlatSpec with IdiomaticMockito with ResetMocksAfterEachTest {
val serviceB: ServiceB = mock[ServiceB]
val serviceA: ServiceA = new ServiceA(serviceB)
"methodA" should "called" in {
serviceA.methodA()
serviceB.methodB wasCalled once // Passes
}
"methodA2" should "called" in {
serviceA.methodA2()
serviceB.methodB wasCalled once // now passes as well
}
}
but IMHO this is a kind of cheating
Upvotes: 2