Add Support for Mockito spies

Add a @SpyBean annotation that can be used to create spies.

Fixes gh-5538
This commit is contained in:
Phillip Webb
2016-04-01 11:45:08 -07:00
parent 1d4f38e440
commit 34070e5a8e
41 changed files with 1649 additions and 313 deletions

View File

@@ -0,0 +1,292 @@
/*
* Copyright 2012-2016 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 java.util.ArrayList;
import java.util.List;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.Answers;
import org.springframework.boot.test.mock.mockito.example.ExampleExtraInterface;
import org.springframework.boot.test.mock.mockito.example.ExampleService;
import org.springframework.boot.test.mock.mockito.example.ExampleServiceCaller;
import org.springframework.boot.test.mock.mockito.example.RealExampleService;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link DefinitionsParser}.
*
* @author Phillip Webb
*/
public class DefinitionsParserTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
private DefinitionsParser parser = new DefinitionsParser();
@Test
public void parseSingleMockBean() {
this.parser.parse(SingleMockBean.class);
assertThat(getDefinitions()).hasSize(1);
assertThat(getMockDefinition(0).getClassToMock()).isEqualTo(ExampleService.class);
}
@Test
public void parseRepeatMockBean() {
this.parser.parse(RepeatMockBean.class);
assertThat(getDefinitions()).hasSize(2);
assertThat(getMockDefinition(0).getClassToMock()).isEqualTo(ExampleService.class);
assertThat(getMockDefinition(1).getClassToMock())
.isEqualTo(ExampleServiceCaller.class);
}
@Test
public void parseMockBeanAttributes() throws Exception {
this.parser.parse(MockBeanAttributes.class);
assertThat(getDefinitions()).hasSize(1);
MockDefinition definition = getMockDefinition(0);
assertThat(definition.getName()).isEqualTo("Name");
assertThat(definition.getClassToMock()).isEqualTo(ExampleService.class);
assertThat(definition.getExtraInterfaces())
.containsExactly(ExampleExtraInterface.class);
assertThat(definition.getAnswer()).isEqualTo(Answers.RETURNS_SMART_NULLS);
assertThat(definition.isSerializable()).isEqualTo(true);
assertThat(definition.getReset()).isEqualTo(MockReset.NONE);
}
@Test
public void parseMockBeanOnClassAndField() throws Exception {
this.parser.parse(MockBeanOnClassAndField.class);
assertThat(getDefinitions()).hasSize(2);
assertThat(getMockDefinition(0).getClassToMock()).isEqualTo(ExampleService.class);
assertThat(getMockDefinition(1).getClassToMock())
.isEqualTo(ExampleServiceCaller.class);
}
@Test
public void parseMockBeanInferClassToMock() throws Exception {
this.parser.parse(MockBeanInferClassToMock.class);
assertThat(getDefinitions()).hasSize(1);
assertThat(getMockDefinition(0).getClassToMock()).isEqualTo(ExampleService.class);
}
@Test
public void parseMockBeanMissingClassToMock() throws Exception {
this.thrown.expect(IllegalStateException.class);
this.thrown.expectMessage("Unable to deduce class to mock");
this.parser.parse(MockBeanMissingClassToMock.class);
}
@Test
public void parseMockBeanMultipleClasses() throws Exception {
this.parser.parse(MockBeanMultipleClasses.class);
assertThat(getDefinitions()).hasSize(2);
assertThat(getMockDefinition(0).getClassToMock()).isEqualTo(ExampleService.class);
assertThat(getMockDefinition(1).getClassToMock())
.isEqualTo(ExampleServiceCaller.class);
}
@Test
public void parseMockBeanMultipleClassesWithName() throws Exception {
this.thrown.expect(IllegalStateException.class);
this.thrown.expectMessage(
"The name attribute can only be used when mocking a single class");
this.parser.parse(MockBeanMultipleClassesWithName.class);
}
@Test
public void parseSingleSpyBean() {
this.parser.parse(SingleSpyBean.class);
assertThat(getDefinitions()).hasSize(1);
assertThat(getSpyDefinition(0).getClassToSpy())
.isEqualTo(RealExampleService.class);
}
@Test
public void parseRepeatSpyBean() {
this.parser.parse(RepeatSpyBean.class);
assertThat(getDefinitions()).hasSize(2);
assertThat(getSpyDefinition(0).getClassToSpy())
.isEqualTo(RealExampleService.class);
assertThat(getSpyDefinition(1).getClassToSpy())
.isEqualTo(ExampleServiceCaller.class);
}
@Test
public void parseSpyBeanAttributes() throws Exception {
this.parser.parse(SpyBeanAttributes.class);
assertThat(getDefinitions()).hasSize(1);
SpyDefinition definition = getSpyDefinition(0);
assertThat(definition.getName()).isEqualTo("Name");
assertThat(definition.getClassToSpy()).isEqualTo(RealExampleService.class);
assertThat(definition.getReset()).isEqualTo(MockReset.NONE);
}
@Test
public void parseSpyBeanOnClassAndField() throws Exception {
this.parser.parse(SpyBeanOnClassAndField.class);
assertThat(getDefinitions()).hasSize(2);
assertThat(getSpyDefinition(0).getClassToSpy())
.isEqualTo(RealExampleService.class);
assertThat(getSpyDefinition(1).getClassToSpy())
.isEqualTo(ExampleServiceCaller.class);
}
@Test
public void parseSpyBeanInferClassToMock() throws Exception {
this.parser.parse(SpyBeanInferClassToMock.class);
assertThat(getDefinitions()).hasSize(1);
assertThat(getSpyDefinition(0).getClassToSpy())
.isEqualTo(RealExampleService.class);
}
@Test
public void parseSpyBeanMissingClassToMock() throws Exception {
this.thrown.expect(IllegalStateException.class);
this.thrown.expectMessage("Unable to deduce class to spy");
this.parser.parse(SpyBeanMissingClassToMock.class);
}
@Test
public void parseSpyBeanMultipleClasses() throws Exception {
this.parser.parse(SpyBeanMultipleClasses.class);
assertThat(getDefinitions()).hasSize(2);
assertThat(getSpyDefinition(0).getClassToSpy())
.isEqualTo(RealExampleService.class);
assertThat(getSpyDefinition(1).getClassToSpy())
.isEqualTo(ExampleServiceCaller.class);
}
@Test
public void parseSpyBeanMultipleClassesWithName() throws Exception {
this.thrown.expect(IllegalStateException.class);
this.thrown.expectMessage(
"The name attribute can only be used when spying a single class");
this.parser.parse(SpyBeanMultipleClassesWithName.class);
}
private MockDefinition getMockDefinition(int index) {
return (MockDefinition) getDefinitions().get(index);
}
private SpyDefinition getSpyDefinition(int index) {
return (SpyDefinition) getDefinitions().get(index);
}
private List<Definition> getDefinitions() {
return new ArrayList<Definition>(this.parser.getDefinitions());
}
@MockBean(ExampleService.class)
static class SingleMockBean {
}
@MockBeans({ @MockBean(ExampleService.class), @MockBean(ExampleServiceCaller.class) })
static class RepeatMockBean {
}
@MockBean(name = "Name", classes = ExampleService.class, extraInterfaces = ExampleExtraInterface.class, answer = Answers.RETURNS_SMART_NULLS, serializable = true, reset = MockReset.NONE)
static class MockBeanAttributes {
}
@MockBean(ExampleService.class)
static class MockBeanOnClassAndField {
@MockBean(ExampleServiceCaller.class)
private Object caller;
}
@MockBean({ ExampleService.class, ExampleServiceCaller.class })
static class MockBeanMultipleClasses {
}
@MockBean(name = "name", classes = { ExampleService.class,
ExampleServiceCaller.class })
static class MockBeanMultipleClassesWithName {
}
static class MockBeanInferClassToMock {
@MockBean
private ExampleService exampleService;
}
@MockBean
static class MockBeanMissingClassToMock {
}
@SpyBean(RealExampleService.class)
static class SingleSpyBean {
}
@SpyBeans({ @SpyBean(RealExampleService.class),
@SpyBean(ExampleServiceCaller.class) })
static class RepeatSpyBean {
}
@SpyBean(name = "Name", classes = RealExampleService.class, reset = MockReset.NONE)
static class SpyBeanAttributes {
}
@SpyBean(RealExampleService.class)
static class SpyBeanOnClassAndField {
@SpyBean(ExampleServiceCaller.class)
private Object caller;
}
@SpyBean({ RealExampleService.class, ExampleServiceCaller.class })
static class SpyBeanMultipleClasses {
}
@SpyBean(name = "name", classes = { RealExampleService.class,
ExampleServiceCaller.class })
static class SpyBeanMultipleClassesWithName {
}
static class SpyBeanInferClassToMock {
@SpyBean
private RealExampleService exampleService;
}
@SpyBean
static class SpyBeanMissingClassToMock {
}
}

View File

@@ -36,7 +36,7 @@ import static org.mockito.BDDMockito.given;
* @author Phillip Webb
*/
@RunWith(SpringRunner.class)
public class OnConfigurationClassForExistingBeanIntegrationTests {
public class MockBeanOnConfigurationClassForExistingBeanIntegrationTests {
@Autowired
private ExampleServiceCaller caller;

View File

@@ -36,7 +36,7 @@ import static org.mockito.BDDMockito.given;
* @author Phillip Webb
*/
@RunWith(SpringRunner.class)
public class OnConfigurationClassForNewBeanIntegrationTests {
public class MockBeanOnConfigurationClassForNewBeanIntegrationTests {
@Autowired
private ExampleServiceCaller caller;

View File

@@ -37,7 +37,7 @@ import static org.mockito.BDDMockito.given;
* @author Phillip Webb
*/
@RunWith(SpringRunner.class)
public class OnConfigurationFieldForExistingBeanIntegrationTests {
public class MockBeanOnConfigurationFieldForExistingBeanIntegrationTests {
@Autowired
private Config config;

View File

@@ -36,7 +36,7 @@ import static org.mockito.BDDMockito.given;
* @author Phillip Webb
*/
@RunWith(SpringRunner.class)
public class OnConfigurationFieldForNewBeanIntegrationTests {
public class MockBeanOnConfigurationFieldForNewBeanIntegrationTests {
@Autowired
private Config config;

View File

@@ -21,8 +21,8 @@ import org.junit.runner.RunWith;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.OnContextHierarchyIntegrationTests.ChildConfig;
import org.springframework.boot.test.mock.mockito.OnContextHierarchyIntegrationTests.ParentConfig;
import org.springframework.boot.test.mock.mockito.MockBeanOnContextHierarchyIntegrationTests.ChildConfig;
import org.springframework.boot.test.mock.mockito.MockBeanOnContextHierarchyIntegrationTests.ParentConfig;
import org.springframework.boot.test.mock.mockito.example.ExampleService;
import org.springframework.boot.test.mock.mockito.example.ExampleServiceCaller;
import org.springframework.context.ApplicationContext;
@@ -42,7 +42,7 @@ import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
@ContextHierarchy({ @ContextConfiguration(classes = ParentConfig.class),
@ContextConfiguration(classes = ChildConfig.class) })
public class OnContextHierarchyIntegrationTests {
public class MockBeanOnContextHierarchyIntegrationTests {
@Autowired
private ChildConfig childConfig;

View File

@@ -37,7 +37,7 @@ import static org.mockito.BDDMockito.given;
*/
@RunWith(SpringRunner.class)
@MockBean(ExampleService.class)
public class OnTestClassForExistingBeanIntegrationTests {
public class MockBeanOnTestClassForExistingBeanIntegrationTests {
@Autowired
private ExampleServiceCaller caller;

View File

@@ -36,7 +36,7 @@ import static org.mockito.BDDMockito.given;
*/
@RunWith(SpringRunner.class)
@MockBean(ExampleService.class)
public class OnTestClassForNewBeanIntegrationTests {
public class MockBeanOnTestClassForNewBeanIntegrationTests {
@Autowired
private ExampleServiceCaller caller;

View File

@@ -31,15 +31,15 @@ import static org.mockito.BDDMockito.given;
/**
* Test {@link MockBean} on a test class field can be used to replace existing beans when
* the context is cached. This test is identical to
* {@link OnTestFieldForExistingBeanCacheIntegrationTests} so one of them should trigger
* application context caching.
* {@link MockBeanOnTestFieldForExistingBeanIntegrationTests} so one of them should
* trigger application context caching.
*
* @author Phillip Webb
* @see OnTestFieldForExistingBeanIntegrationTests
* @see MockBeanOnTestFieldForExistingBeanIntegrationTests
*/
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = OnTestFieldForExistingBeanConfig.class)
public class OnTestFieldForExistingBeanCacheIntegrationTests {
@ContextConfiguration(classes = MockBeanOnTestFieldForExistingBeanConfig.class)
public class MockBeanOnTestFieldForExistingBeanCacheIntegrationTests {
@MockBean
private ExampleService exampleService;

View File

@@ -21,14 +21,14 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* Config for {@link OnTestFieldForExistingBeanIntegrationTests} and
* {@link OnTestFieldForExistingBeanCacheIntegrationTests}. Extracted to a shared config
* Config for {@link MockBeanOnTestFieldForExistingBeanIntegrationTests} and
* {@link MockBeanOnTestFieldForExistingBeanCacheIntegrationTests}. Extracted to a shared config
* to trigger caching.
*
* @author Phillip Webb
*/
@Configuration
@Import(ExampleServiceCaller.class)
public class OnTestFieldForExistingBeanConfig {
public class MockBeanOnTestFieldForExistingBeanConfig {
}

View File

@@ -32,11 +32,11 @@ import static org.mockito.BDDMockito.given;
* Test {@link MockBean} on a test class field can be used to replace existing beans.
*
* @author Phillip Webb
* @see OnTestFieldForExistingBeanCacheIntegrationTests
* @see MockBeanOnTestFieldForExistingBeanCacheIntegrationTests
*/
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = OnTestFieldForExistingBeanConfig.class)
public class OnTestFieldForExistingBeanIntegrationTests {
@ContextConfiguration(classes = MockBeanOnTestFieldForExistingBeanConfig.class)
public class MockBeanOnTestFieldForExistingBeanIntegrationTests {
@MockBean
private ExampleService exampleService;

View File

@@ -36,7 +36,7 @@ import static org.mockito.BDDMockito.given;
* @author Phillip Webb
*/
@RunWith(SpringRunner.class)
public class OnTestFieldForNewBeanIntegrationTests {
public class MockBeanOnTestFieldForNewBeanIntegrationTests {
@MockBean
private ExampleService exampleService;

View File

@@ -1,184 +0,0 @@
/*
* Copyright 2012-2016 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 java.util.ArrayList;
import java.util.List;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.Answers;
import org.springframework.boot.test.mock.mockito.example.ExampleExtraInterface;
import org.springframework.boot.test.mock.mockito.example.ExampleService;
import org.springframework.boot.test.mock.mockito.example.ExampleServiceCaller;
import org.springframework.boot.test.mock.mockito.example.MyMockBean;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link MockDefinitionsParser}.
*
* @author Phillip Webb
*/
public class MockDefinitionsParserTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
private MockDefinitionsParser parser = new MockDefinitionsParser();
@Test
public void parseSingleMockBean() {
this.parser.parse(SingleMockBean.class);
assertThat(getDefinitions()).hasSize(1);
assertThat(getDefinition(0).getClassToMock()).isEqualTo(ExampleService.class);
}
@Test
public void parseRepeatMockBean() {
this.parser.parse(RepeatMockBean.class);
assertThat(getDefinitions()).hasSize(2);
assertThat(getDefinition(0).getClassToMock()).isEqualTo(ExampleService.class);
assertThat(getDefinition(1).getClassToMock())
.isEqualTo(ExampleServiceCaller.class);
}
@Test
@Ignore // See SPR-13973
public void parseMetaMockBean() {
this.parser.parse(MetaMockBean.class);
assertThat(getDefinitions()).hasSize(1);
assertThat(getDefinition(0).getClassToMock()).isEqualTo(ExampleService.class);
}
@Test
public void parseMockBeanAttributes() throws Exception {
this.parser.parse(MockBeanAttributes.class);
assertThat(getDefinitions()).hasSize(1);
MockDefinition definition = getDefinition(0);
assertThat(definition.getName()).isEqualTo("Name");
assertThat(definition.getClassToMock()).isEqualTo(ExampleService.class);
assertThat(definition.getExtraInterfaces())
.containsExactly(ExampleExtraInterface.class);
assertThat(definition.getAnswer()).isEqualTo(Answers.RETURNS_SMART_NULLS);
assertThat(definition.isSerializable()).isEqualTo(true);
assertThat(definition.getReset()).isEqualTo(MockReset.NONE);
}
@Test
public void parseOnClassAndField() throws Exception {
this.parser.parse(OnClassAndField.class);
assertThat(getDefinitions()).hasSize(2);
assertThat(getDefinition(0).getClassToMock()).isEqualTo(ExampleService.class);
assertThat(getDefinition(1).getClassToMock())
.isEqualTo(ExampleServiceCaller.class);
}
@Test
public void parseInferClassToMock() throws Exception {
this.parser.parse(InferClassToMock.class);
assertThat(getDefinitions()).hasSize(1);
assertThat(getDefinition(0).getClassToMock()).isEqualTo(ExampleService.class);
}
@Test
public void parseMissingClassToMock() throws Exception {
this.thrown.expect(IllegalStateException.class);
this.thrown.expectMessage("Unable to deduce class to mock");
this.parser.parse(MissingClassToMock.class);
}
@Test
public void parseMultipleClasses() throws Exception {
this.parser.parse(MultipleClasses.class);
assertThat(getDefinitions()).hasSize(2);
assertThat(getDefinition(0).getClassToMock()).isEqualTo(ExampleService.class);
assertThat(getDefinition(1).getClassToMock())
.isEqualTo(ExampleServiceCaller.class);
}
@Test
public void parseMultipleClassesWithName() throws Exception {
this.thrown.expect(IllegalStateException.class);
this.thrown.expectMessage(
"The name attribute can only be used when mocking a single class");
this.parser.parse(MultipleClassesWithName.class);
}
private MockDefinition getDefinition(int index) {
return getDefinitions().get(index);
}
private List<MockDefinition> getDefinitions() {
return new ArrayList<MockDefinition>(this.parser.getDefinitions());
}
@MockBean(ExampleService.class)
static class SingleMockBean {
}
@MockBeans({ @MockBean(ExampleService.class), @MockBean(ExampleServiceCaller.class) })
static class RepeatMockBean {
}
@MyMockBean(ExampleService.class)
static class MetaMockBean {
}
@MockBean(name = "Name", classes = ExampleService.class, extraInterfaces = ExampleExtraInterface.class, answer = Answers.RETURNS_SMART_NULLS, serializable = true, reset = MockReset.NONE)
static class MockBeanAttributes {
}
@MockBean(ExampleService.class)
static class OnClassAndField {
@MockBean(ExampleServiceCaller.class)
private Object caller;
}
@MockBean({ ExampleService.class, ExampleServiceCaller.class })
static class MultipleClasses {
}
@MockBean(name = "name", classes = { ExampleService.class,
ExampleServiceCaller.class })
static class MultipleClassesWithName {
}
static class InferClassToMock {
@MockBean
private ExampleService exampleService;
}
@MockBean
static class MissingClassToMock {
}
}

View File

@@ -37,13 +37,13 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
/**
* Tests for {@link MockitoInitializeTestExecutionListener}.
* Tests for {@link MockitoTestExecutionListener}.
*
* @author Phillip Webb
*/
public class MockitoInitializeTestExecutionListenerTests {
private MockitoInitializeTestExecutionListener listener = new MockitoInitializeTestExecutionListener();
private MockitoTestExecutionListener listener = new MockitoTestExecutionListener();
@Mock
private ApplicationContext applicationContext;

View File

@@ -27,8 +27,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Test for {@link MockitoPostProcessor}. See also the integration tests in the
* {@code runner} package.
* Test for {@link MockitoPostProcessor}. See also the integration tests.
*
* @author Phillip Webb
*/

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2012-2016 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.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verify;
/**
* Test {@link SpyBean} on a configuration class can be used to spy existing beans.
*
* @author Phillip Webb
*/
@RunWith(SpringRunner.class)
public class SpyBeanOnConfigurationClassForExistingBeanIntegrationTests {
@Autowired
private ExampleServiceCaller caller;
@Test
public void testSpying() throws Exception {
assertThat(this.caller.sayGreeting()).isEqualTo("I say simple");
verify(this.caller.getService()).greeting();
}
@Configuration
@SpyBean(SimpleExampleService.class)
@Import({ ExampleServiceCaller.class, SimpleExampleService.class })
static class Config {
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2012-2016 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.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verify;
/**
* Test {@link SpyBean} on a configuration class can be used to inject new spy instances.
*
* @author Phillip Webb
*/
@RunWith(SpringRunner.class)
public class SpyBeanOnConfigurationClassForNewBeanIntegrationTests {
@Autowired
private ExampleServiceCaller caller;
@Test
public void testSpying() throws Exception {
assertThat(this.caller.sayGreeting()).isEqualTo("I say simple");
verify(this.caller.getService()).greeting();
}
@Configuration
@SpyBean(SimpleExampleService.class)
@Import(ExampleServiceCaller.class)
static class Config {
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2012-2016 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.boot.test.mock.mockito.example.SimpleExampleService;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verify;
/**
* Test {@link SpyBean} on a field on a {@code @Configuration} class can be used to
* replace existing beans.
*
* @author Phillip Webb
*/
@RunWith(SpringRunner.class)
public class SpyBeanOnConfigurationFieldForExistingBeanIntegrationTests {
@Autowired
private Config config;
@Autowired
private ExampleServiceCaller caller;
@Test
public void testSpying() throws Exception {
assertThat(this.caller.sayGreeting()).isEqualTo("I say simple");
verify(this.config.exampleService).greeting();
}
@Configuration
@Import({ ExampleServiceCaller.class, SimpleExampleService.class })
static class Config {
@SpyBean
private ExampleService exampleService;
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright 2012-2016 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.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verify;
/**
* Test {@link SpyBean} on a field on a {@code @Configuration} class can be used to inject
* new spy instances.
*
* @author Phillip Webb
*/
@RunWith(SpringRunner.class)
public class SpyBeanOnConfigurationFieldForNewBeanIntegrationTests {
@Autowired
private Config config;
@Autowired
private ExampleServiceCaller caller;
@Test
public void testSpying() throws Exception {
assertThat(this.caller.sayGreeting()).isEqualTo("I say simple");
verify(this.config.exampleService).greeting();
}
@Configuration
@Import(ExampleServiceCaller.class)
static class Config {
@SpyBean
private SimpleExampleService exampleService;
}
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright 2012-2016 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.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.SpyBeanOnContextHierarchyIntegrationTests.ChildConfig;
import org.springframework.boot.test.mock.mockito.SpyBeanOnContextHierarchyIntegrationTests.ParentConfig;
import org.springframework.boot.test.mock.mockito.example.ExampleService;
import org.springframework.boot.test.mock.mockito.example.ExampleServiceCaller;
import org.springframework.boot.test.mock.mockito.example.SimpleExampleService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.ContextHierarchy;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Test {@link SpyBean} can be used with a {@link ContextHierarchy}.
*
* @author Phillip Webb
*/
@RunWith(SpringRunner.class)
@ContextHierarchy({ @ContextConfiguration(classes = ParentConfig.class),
@ContextConfiguration(classes = ChildConfig.class) })
public class SpyBeanOnContextHierarchyIntegrationTests {
@Autowired
private ChildConfig childConfig;
@Test
public void testSpying() throws Exception {
ApplicationContext context = this.childConfig.getContext();
ApplicationContext parentContext = context.getParent();
assertThat(parentContext.getBeanNamesForType(ExampleService.class)).hasSize(1);
assertThat(parentContext.getBeanNamesForType(ExampleServiceCaller.class))
.hasSize(0);
assertThat(context.getBeanNamesForType(ExampleService.class)).hasSize(0);
assertThat(context.getBeanNamesForType(ExampleServiceCaller.class)).hasSize(1);
assertThat(context.getBean(ExampleService.class)).isNotNull();
assertThat(context.getBean(ExampleServiceCaller.class)).isNotNull();
}
@Configuration
@SpyBean(SimpleExampleService.class)
static class ParentConfig {
}
@Configuration
@SpyBean(ExampleServiceCaller.class)
static class ChildConfig implements ApplicationContextAware {
private ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.context = applicationContext;
}
public ApplicationContext getContext() {
return this.context;
}
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2012-2016 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.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verify;
/**
* Test {@link SpyBean} on a test class can be used to replace existing beans.
*
* @author Phillip Webb
*/
@RunWith(SpringRunner.class)
@SpyBean(SimpleExampleService.class)
public class SpyBeanOnTestClassForExistingBeanIntegrationTests {
@Autowired
private ExampleServiceCaller caller;
@Test
public void testSpying() throws Exception {
assertThat(this.caller.sayGreeting()).isEqualTo("I say simple");
verify(this.caller.getService()).greeting();
}
@Configuration
@Import({ ExampleServiceCaller.class, SimpleExampleService.class })
static class Config {
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2012-2016 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.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verify;
/**
* Test {@link SpyBean} on a test class can be used to inject new mock instances.
*
* @author Phillip Webb
*/
@RunWith(SpringRunner.class)
@SpyBean(SimpleExampleService.class)
public class SpyBeanOnTestClassForNewBeanIntegrationTests {
@Autowired
private ExampleServiceCaller caller;
@Test
public void testSpying() throws Exception {
assertThat(this.caller.sayGreeting()).isEqualTo("I say simple");
verify(this.caller.getService()).greeting();
}
@Configuration
@Import(ExampleServiceCaller.class)
static class Config {
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2012-2016 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.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verify;
/**
* Test {@link SpyBean} on a test class field can be used to replace existing beans when
* the context is cached. This test is identical to
* {@link SpyBeanOnTestFieldForExistingBeanIntegrationTests} so one of them should trigger
* application context caching.
*
* @author Phillip Webb
* @see SpyBeanOnTestFieldForExistingBeanIntegrationTests
*/
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = SpyBeanOnTestFieldForExistingBeanConfig.class)
public class SpyBeanOnTestFieldForExistingBeanCacheIntegrationTests {
@SpyBean
private SimpleExampleService exampleService;
@Autowired
private ExampleServiceCaller caller;
@Test
public void testSpying() throws Exception {
assertThat(this.caller.sayGreeting()).isEqualTo("I say simple");
verify(this.caller.getService()).greeting();
}
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright 2012-2016 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.springframework.boot.test.mock.mockito.example.ExampleServiceCaller;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* Config for {@link SpyBeanOnTestFieldForExistingBeanIntegrationTests} and
* {@link SpyBeanOnTestFieldForExistingBeanCacheIntegrationTests}. Extracted to a shared
* config to trigger caching.
*
* @author Phillip Webb
*/
@Configuration
@Import(ExampleServiceCaller.class)
public class SpyBeanOnTestFieldForExistingBeanConfig {
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2012-2016 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.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verify;
/**
* Test {@link SpyBean} on a test class field can be used to replace existing beans.
*
* @author Phillip Webb
* @see SpyBeanOnTestFieldForExistingBeanCacheIntegrationTests
*/
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = MockBeanOnTestFieldForExistingBeanConfig.class)
public class SpyBeanOnTestFieldForExistingBeanIntegrationTests {
@SpyBean
private SimpleExampleService exampleService;
@Autowired
private ExampleServiceCaller caller;
@Test
public void testSpying() throws Exception {
assertThat(this.caller.sayGreeting()).isEqualTo("I say simple");
verify(this.caller.getService()).greeting();
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2012-2016 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.boot.test.mock.mockito.example.SimpleExampleService;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verify;
/**
* Test {@link SpyBean} on a test class field can be used to inject new mock instances.
*
* @author Phillip Webb
*/
@RunWith(SpringRunner.class)
public class SpyBeanOnTestFieldForNewBeanIntegrationTests {
@SpyBean
private ExampleService exampleService;
@Autowired
private ExampleServiceCaller caller;
@Test
public void testSpying() throws Exception {
assertThat(this.caller.sayGreeting()).isEqualTo("I say simple");
verify(this.caller.getService()).greeting();
}
@Configuration
@Import({ ExampleServiceCaller.class, SimpleExampleService.class })
static class Config {
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright 2012-2016 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.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.Answers;
import org.mockito.internal.util.MockUtil;
import org.mockito.mock.MockCreationSettings;
import org.springframework.boot.test.mock.mockito.example.ExampleService;
import org.springframework.boot.test.mock.mockito.example.ExampleServiceCaller;
import org.springframework.boot.test.mock.mockito.example.RealExampleService;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link SpyDefinition}.
*
* @author Phillip Webb
*/
public class SpyDefinitionTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void ClassToSpyMustNotBeNull() throws Exception {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("ClassToSpy must not be null");
new SpyDefinition(null, null, null);
}
@Test
public void createWithDefaults() throws Exception {
SpyDefinition definition = new SpyDefinition(null, RealExampleService.class,
null);
assertThat(definition.getName()).isNull();
assertThat(definition.getClassToSpy()).isEqualTo(RealExampleService.class);
assertThat(definition.getReset()).isEqualTo(MockReset.AFTER);
}
@Test
public void createExplicit() throws Exception {
SpyDefinition definition = new SpyDefinition("name", RealExampleService.class,
MockReset.BEFORE);
assertThat(definition.getName()).isEqualTo("name");
assertThat(definition.getClassToSpy()).isEqualTo(RealExampleService.class);
assertThat(definition.getReset()).isEqualTo(MockReset.BEFORE);
}
@Test
public void createSpy() throws Exception {
SpyDefinition definition = new SpyDefinition("name", RealExampleService.class,
MockReset.BEFORE);
RealExampleService spy = definition.createSpy(new RealExampleService("hello"));
MockCreationSettings<?> settings = new MockUtil().getMockSettings(spy);
assertThat(spy).isInstanceOf(ExampleService.class);
assertThat(settings.getMockName().toString()).isEqualTo("name");
assertThat(settings.getDefaultAnswer())
.isEqualTo(Answers.CALLS_REAL_METHODS.get());
assertThat(MockReset.get(spy)).isEqualTo(MockReset.BEFORE);
}
@Test
public void createSpyWhenNullInstanceShouldThrowException() throws Exception {
SpyDefinition definition = new SpyDefinition("name", RealExampleService.class,
MockReset.BEFORE);
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("Instance must not be null");
definition.createSpy(null);
}
@Test
public void createSpyWhenWrongInstanceShouldThrowException() throws Exception {
SpyDefinition definition = new SpyDefinition("name", RealExampleService.class,
MockReset.BEFORE);
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("must be an instance of");
definition.createSpy(new ExampleServiceCaller(null));
}
@Test
public void createSpyTwice() throws Exception {
SpyDefinition definition = new SpyDefinition("name", RealExampleService.class,
MockReset.BEFORE);
Object instance = new RealExampleService("hello");
instance = definition.createSpy(instance);
instance = definition.createSpy(instance);
}
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2012-2016 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.example;
/**
* Example service implementation for spy tests.
*
* @author Phillip Webb
*/
public class RealExampleService implements ExampleService {
private final String greeting;
public RealExampleService(String greeting) {
this.greeting = greeting;
}
@Override
public String greeting() {
return this.greeting;
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2012-2016 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.example;
/**
* Example service implementation for spy tests.
*
* @author Phillip Webb
*/
public class SimpleExampleService extends RealExampleService {
public SimpleExampleService() {
super("simple");
}
}