'How to reset a method mock in Spock?
I had a mocked bean in a configuration:
@Profile('test')
@Configuration
class TestSecurityConfig {
private final mockFactory = new DetachedMockFactory()
@Primary @Bean
AuthUserDetailsProvider authUserDetailsProvider() {
mockFactory.Stub(AuthUserDetailsProvider)
}
}
By default, I mock a method call is setup()
method for all tests.
def setup() {
authProvider.authenticationPrincipal >> random(authUserDetails)
}
By in a specific test, I need to override the method mock
def 'exercise missed user processing'() {
given: 'no user data'
authProvider.authenticationPrincipal >> emptyUser
...
}
But it doesn't work. How can I override a method mocking in Spock? Is there any way to reset mock interceptions manually?
Solution 1:[1]
Interactions defined in then
blocks will have precedence over those defined in given
/setup
, for the preceding when
block. Normally, you pair them with assertions, i.e., 1 * ...
but it works for plain stubbing too.
import spock.lang.*
class ASpec extends Specification {
List myList = Mock()
def setup() {
myList.get(0) >> 1
}
def "default behavior"() {
expect:
myList.get(0) == 1
}
def "override behavior"() {
when:
def result = myList.get(0)
then:
myList.get(0) >> 42
result == 42
}
}
So in your case:
def 'exercise missed user processing'() {
when:
...
then:
1 * authProvider.authenticationPrincipal >> emptyUser
...
}
Solution 2:[2]
But it doesn't work?
Whatever you put in setup will be executed before each test. If you don't want that, then the code probably shouldn't be in setup.
How can I override a method mocking in Spock?
If by "override" you mean undo what was done in setup and then do something else, I am not aware of a way to do that.
Is there any way to reset mock interceptions manually?
Not that I am aware of. It is unusual to tell the mock that you want a certain behavior and later tell the mock that you have changed your mind.
Solution 3:[3]
The answer from @leonard-brünings is quite helpful, but I feel that it missed to explain the below part of the question with a more direct and simple explanation:
But it doesn't work.
The Where to Declare Interactions section has the explanation:
When an invocation on a mock object occurs, it is matched against interactions in the interactions' declared order. If an invocation matches multiple interactions, the earliest declared interaction that hasn’t reached its upper invocation limit will win.
Because Spock sees the interaction in setup
before the given:
section, what this means is that the one defined in setup
takes precedence.
How can I override a method mocking in Spock?
This is already explained and shown in the answer from @leonard-brünings, but just want to quote the relevant section from the same above documentation:
There is one exception to this rule: Interactions declared in a
then:
block are matched against before any other interactions. This allows to override interactions declared in, say, a setup method with interactions declared in athen:
block.
Which is why the solution is to move the interaction from the given:
block to then:
block.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | kriegaex |
Solution 2 | Jeff Scott Brown |
Solution 3 | haridsv |