Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
spring-boot
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DEMO
spring-boot
Commits
aac88502
Commit
aac88502
authored
Feb 05, 2018
by
Andy Wilkinson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Reinject mocks when context is dirtied before each method
Closes gh-11903
parent
61cba640
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
231 additions
and
16 deletions
+231
-16
MockitoTestExecutionListener.java
.../boot/test/mock/mockito/MockitoTestExecutionListener.java
+81
-15
MockBeanWithDirtiesContextClassModeBeforeMethodIntegrationTests.java
...hDirtiesContextClassModeBeforeMethodIntegrationTests.java
+63
-0
MockitoTestExecutionListenerTests.java
.../test/mock/mockito/MockitoTestExecutionListenerTests.java
+25
-1
SpyBeanWithDirtiesContextClassModeBeforeMethodIntegrationTests.java
...hDirtiesContextClassModeBeforeMethodIntegrationTests.java
+62
-0
No files found.
spring-boot-test/src/main/java/org/springframework/boot/test/mock/mockito/MockitoTestExecutionListener.java
View file @
aac88502
/*
/*
* Copyright 2012-201
6
the original author or authors.
* Copyright 2012-201
8
the original author or authors.
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may not use this file except in compliance with the License.
...
@@ -24,10 +24,10 @@ import java.util.Set;
...
@@ -24,10 +24,10 @@ import java.util.Set;
import
org.mockito.Captor
;
import
org.mockito.Captor
;
import
org.mockito.MockitoAnnotations
;
import
org.mockito.MockitoAnnotations
;
import
org.springframework.context.ApplicationContext
;
import
org.springframework.test.context.TestContext
;
import
org.springframework.test.context.TestContext
;
import
org.springframework.test.context.TestExecutionListener
;
import
org.springframework.test.context.TestExecutionListener
;
import
org.springframework.test.context.support.AbstractTestExecutionListener
;
import
org.springframework.test.context.support.AbstractTestExecutionListener
;
import
org.springframework.test.context.support.DependencyInjectionTestExecutionListener
;
import
org.springframework.util.ReflectionUtils
;
import
org.springframework.util.ReflectionUtils
;
import
org.springframework.util.ReflectionUtils.FieldCallback
;
import
org.springframework.util.ReflectionUtils.FieldCallback
;
...
@@ -37,16 +37,35 @@ import org.springframework.util.ReflectionUtils.FieldCallback;
...
@@ -37,16 +37,35 @@ import org.springframework.util.ReflectionUtils.FieldCallback;
* annotations.
* annotations.
*
*
* @author Phillip Webb
* @author Phillip Webb
* @author Andy Wilkinson
* @since 1.4.2
* @since 1.4.2
*/
*/
public
class
MockitoTestExecutionListener
extends
AbstractTestExecutionListener
{
public
class
MockitoTestExecutionListener
extends
AbstractTestExecutionListener
{
@Override
@Override
public
void
prepareTestInstance
(
TestContext
testContext
)
throws
Exception
{
public
void
prepareTestInstance
(
TestContext
testContext
)
throws
Exception
{
initMocks
(
testContext
);
injectFields
(
testContext
);
}
@Override
public
void
beforeTestMethod
(
TestContext
testContext
)
throws
Exception
{
if
(
Boolean
.
TRUE
.
equals
(
testContext
.
getAttribute
(
DependencyInjectionTestExecutionListener
.
REINJECT_DEPENDENCIES_ATTRIBUTE
)))
{
initMocks
(
testContext
);
reinjectFields
(
testContext
);
}
}
@Override
public
int
getOrder
()
{
return
1950
;
}
private
void
initMocks
(
TestContext
testContext
)
{
if
(
hasMockitoAnnotations
(
testContext
))
{
if
(
hasMockitoAnnotations
(
testContext
))
{
MockitoAnnotations
.
initMocks
(
testContext
.
getTestInstance
());
MockitoAnnotations
.
initMocks
(
testContext
.
getTestInstance
());
}
}
injectFields
(
testContext
);
}
}
private
boolean
hasMockitoAnnotations
(
TestContext
testContext
)
{
private
boolean
hasMockitoAnnotations
(
TestContext
testContext
)
{
...
@@ -56,21 +75,46 @@ public class MockitoTestExecutionListener extends AbstractTestExecutionListener
...
@@ -56,21 +75,46 @@ public class MockitoTestExecutionListener extends AbstractTestExecutionListener
}
}
private
void
injectFields
(
TestContext
testContext
)
{
private
void
injectFields
(
TestContext
testContext
)
{
postProcessFields
(
testContext
,
new
MockitoFieldHandler
()
{
@Override
public
void
handle
(
MockitoField
mockitoField
,
MockitoPostProcessor
postProcessor
)
{
postProcessor
.
inject
(
mockitoField
.
field
,
mockitoField
.
target
,
mockitoField
.
definition
);
}
});
}
private
void
reinjectFields
(
final
TestContext
testContext
)
{
postProcessFields
(
testContext
,
new
MockitoFieldHandler
()
{
@Override
public
void
handle
(
MockitoField
mockitoField
,
MockitoPostProcessor
postProcessor
)
{
ReflectionUtils
.
makeAccessible
(
mockitoField
.
field
);
ReflectionUtils
.
setField
(
mockitoField
.
field
,
testContext
.
getTestInstance
(),
null
);
postProcessor
.
inject
(
mockitoField
.
field
,
mockitoField
.
target
,
mockitoField
.
definition
);
}
});
}
private
void
postProcessFields
(
TestContext
testContext
,
MockitoFieldHandler
handler
)
{
DefinitionsParser
parser
=
new
DefinitionsParser
();
DefinitionsParser
parser
=
new
DefinitionsParser
();
parser
.
parse
(
testContext
.
getTestClass
());
parser
.
parse
(
testContext
.
getTestClass
());
if
(!
parser
.
getDefinitions
().
isEmpty
())
{
if
(!
parser
.
getDefinitions
().
isEmpty
())
{
injectFields
(
testContext
,
parser
);
MockitoPostProcessor
postProcessor
=
testContext
.
getApplicationContext
()
}
.
getBean
(
MockitoPostProcessor
.
class
);
}
for
(
Definition
definition
:
parser
.
getDefinitions
())
{
Field
field
=
parser
.
getField
(
definition
);
private
void
injectFields
(
TestContext
testContext
,
DefinitionsParser
parser
)
{
if
(
field
!=
null
)
{
ApplicationContext
applicationContext
=
testContext
.
getApplicationContext
();
handler
.
handle
(
new
MockitoField
(
field
,
testContext
.
getTestInstance
(),
MockitoPostProcessor
postProcessor
=
applicationContext
definition
),
postProcessor
);
.
getBean
(
MockitoPostProcessor
.
class
);
}
for
(
Definition
definition
:
parser
.
getDefinitions
())
{
Field
field
=
parser
.
getField
(
definition
);
if
(
field
!=
null
)
{
postProcessor
.
inject
(
field
,
testContext
.
getTestInstance
(),
definition
);
}
}
}
}
}
}
...
@@ -98,4 +142,26 @@ public class MockitoTestExecutionListener extends AbstractTestExecutionListener
...
@@ -98,4 +142,26 @@ public class MockitoTestExecutionListener extends AbstractTestExecutionListener
}
}
private
static
final
class
MockitoField
{
private
final
Field
field
;
private
final
Object
target
;
private
final
Definition
definition
;
private
MockitoField
(
Field
field
,
Object
instance
,
Definition
definition
)
{
this
.
field
=
field
;
this
.
target
=
instance
;
this
.
definition
=
definition
;
}
}
private
interface
MockitoFieldHandler
{
void
handle
(
MockitoField
mockitoField
,
MockitoPostProcessor
postProcessor
);
}
}
}
spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockBeanWithDirtiesContextClassModeBeforeMethodIntegrationTests.java
0 → 100644
View file @
aac88502
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
springframework
.
boot
.
test
.
mock
.
mockito
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.boot.test.mock.mockito.example.ExampleService
;
import
org.springframework.boot.test.mock.mockito.example.ExampleServiceCaller
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Import
;
import
org.springframework.test.annotation.DirtiesContext
;
import
org.springframework.test.annotation.DirtiesContext.ClassMode
;
import
org.springframework.test.annotation.DirtiesContext.MethodMode
;
import
org.springframework.test.context.junit4.SpringRunner
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
import
static
org
.
mockito
.
BDDMockito
.
given
;
/**
* Integration tests for using {@link MockBean} with {@link DirtiesContext} and
* {@link MethodMode#BEFORE_METHOD}.
*
* @author Andy Wilkinson
*/
@RunWith
(
SpringRunner
.
class
)
@DirtiesContext
(
classMode
=
ClassMode
.
BEFORE_EACH_TEST_METHOD
)
public
class
MockBeanWithDirtiesContextClassModeBeforeMethodIntegrationTests
{
@MockBean
private
ExampleService
exampleService
;
@Autowired
private
ExampleServiceCaller
caller
;
@Test
public
void
testMocking
()
throws
Exception
{
given
(
this
.
exampleService
.
greeting
()).
willReturn
(
"Boot"
);
assertThat
(
this
.
caller
.
sayGreeting
()).
isEqualTo
(
"I say Boot"
);
}
@Configuration
@Import
(
ExampleServiceCaller
.
class
)
static
class
Config
{
}
}
spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/MockitoTestExecutionListenerTests.java
View file @
aac88502
/*
/*
* Copyright 2012-201
6
the original author or authors.
* Copyright 2012-201
8
the original author or authors.
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may not use this file except in compliance with the License.
...
@@ -28,6 +28,7 @@ import org.mockito.MockitoAnnotations;
...
@@ -28,6 +28,7 @@ import org.mockito.MockitoAnnotations;
import
org.springframework.context.ApplicationContext
;
import
org.springframework.context.ApplicationContext
;
import
org.springframework.test.context.TestContext
;
import
org.springframework.test.context.TestContext
;
import
org.springframework.test.context.support.DependencyInjectionTestExecutionListener
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
import
static
org
.
mockito
.
BDDMockito
.
given
;
import
static
org
.
mockito
.
BDDMockito
.
given
;
...
@@ -35,6 +36,7 @@ import static org.mockito.Matchers.any;
...
@@ -35,6 +36,7 @@ import static org.mockito.Matchers.any;
import
static
org
.
mockito
.
Matchers
.
eq
;
import
static
org
.
mockito
.
Matchers
.
eq
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
verifyNoMoreInteractions
;
/**
/**
* Tests for {@link MockitoTestExecutionListener}.
* Tests for {@link MockitoTestExecutionListener}.
...
@@ -78,6 +80,28 @@ public class MockitoTestExecutionListenerTests {
...
@@ -78,6 +80,28 @@ public class MockitoTestExecutionListenerTests {
assertThat
(
this
.
fieldCaptor
.
getValue
().
getName
()).
isEqualTo
(
"mockBean"
);
assertThat
(
this
.
fieldCaptor
.
getValue
().
getName
()).
isEqualTo
(
"mockBean"
);
}
}
@Test
public
void
beforeTestMethodShouldDoNothingWhenDirtiesContextAttributeIsNotSet
()
throws
Exception
{
WithMockBean
instance
=
new
WithMockBean
();
this
.
listener
.
beforeTestMethod
(
mockTestContext
(
instance
));
verifyNoMoreInteractions
(
this
.
postProcessor
);
}
@Test
public
void
beforeTestMethodShouldInjectMockBeanWhenDirtiesContextAttributeIsSet
()
throws
Exception
{
WithMockBean
instance
=
new
WithMockBean
();
TestContext
mockTestContext
=
mockTestContext
(
instance
);
given
(
mockTestContext
.
getAttribute
(
DependencyInjectionTestExecutionListener
.
REINJECT_DEPENDENCIES_ATTRIBUTE
))
.
willReturn
(
Boolean
.
TRUE
);
this
.
listener
.
beforeTestMethod
(
mockTestContext
);
verify
(
this
.
postProcessor
).
inject
(
this
.
fieldCaptor
.
capture
(),
eq
(
instance
),
(
MockDefinition
)
any
());
assertThat
(
this
.
fieldCaptor
.
getValue
().
getName
()).
isEqualTo
(
"mockBean"
);
}
@SuppressWarnings
({
"unchecked"
,
"rawtypes"
})
@SuppressWarnings
({
"unchecked"
,
"rawtypes"
})
private
TestContext
mockTestContext
(
Object
instance
)
{
private
TestContext
mockTestContext
(
Object
instance
)
{
TestContext
testContext
=
mock
(
TestContext
.
class
);
TestContext
testContext
=
mock
(
TestContext
.
class
);
...
...
spring-boot-test/src/test/java/org/springframework/boot/test/mock/mockito/SpyBeanWithDirtiesContextClassModeBeforeMethodIntegrationTests.java
0 → 100644
View file @
aac88502
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
springframework
.
boot
.
test
.
mock
.
mockito
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.boot.test.mock.mockito.example.ExampleServiceCaller
;
import
org.springframework.boot.test.mock.mockito.example.SimpleExampleService
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Import
;
import
org.springframework.test.annotation.DirtiesContext
;
import
org.springframework.test.annotation.DirtiesContext.ClassMode
;
import
org.springframework.test.annotation.DirtiesContext.MethodMode
;
import
org.springframework.test.context.junit4.SpringRunner
;
import
static
org
.
mockito
.
Mockito
.
verify
;
/**
* Integration tests for using {@link SpyBean} with {@link DirtiesContext} and
* {@link MethodMode#BEFORE_METHOD}.
*
* @author Andy Wilkinson
*/
@RunWith
(
SpringRunner
.
class
)
@DirtiesContext
(
classMode
=
ClassMode
.
BEFORE_EACH_TEST_METHOD
)
public
class
SpyBeanWithDirtiesContextClassModeBeforeMethodIntegrationTests
{
@SpyBean
private
SimpleExampleService
exampleService
;
@Autowired
private
ExampleServiceCaller
caller
;
@Test
public
void
testSpying
()
throws
Exception
{
this
.
caller
.
sayGreeting
();
verify
(
this
.
exampleService
).
greeting
();
}
@Configuration
@Import
(
ExampleServiceCaller
.
class
)
static
class
Config
{
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment