在 Spring 上下文加载实际的 Spring Bean 之前是否模拟了一个模拟 bean (@MockBean)?
Is a mocked bean (@MockBean) mocked before the Spring Context loads the actual Spring Bean?
让我们以下面的例子为例。
@Autowired
@MockBean
private Foo foobar;
Spring 上下文是否先加载 class Foo
,然后再应用模拟?或者 @Mockbean
是否以某种方式被检测到,并且 Spring 创建并应用模拟而不是将 class Foo
加载到 Spring 上下文中。我怀疑是后者,但我想确认一下。
Spring会抛出异常。
让我们定义 class Foo.
@Component
public class Foo {
public Foo() {
System.out.println("I am not a mock");
}
}
每当使用 @Autowired
进行测试时,spring 都会注入一个 Foo 实例,并且构造函数将打印 "I am not a mock"
,如下面的代码所示。
@SpringBootTest(classes = Main.class)
@RunWith(SpringRunner.class)
public class FooTest {
@Autowired
Foo foo;
@Test
public void test() {
System.out.println(foo);
}
}
另一方面,使用@MockBean,spring不会创建真正的bean,也不会打印构造函数中的消息。此场景由以下代码表示。
@SpringBootTest(classes = Main.class)
@RunWith(SpringRunner.class)
public class FooTest {
@MockBean
Foo foo;
@Test
public void test() {
System.out.println(foo);
}
}
但是,当您尝试同时使用这两个注释时,spring 将抛出由 IllegalStateException
引起的 BeanCreationException
。这意味着字段 foo 不能具有现有值。这种情况会在执行下面的代码时发生:
@SpringBootTest(classes = Main.class)
@RunWith(SpringRunner.class)
public class FooTest {
// this will not work
@Autowired
@MockBean
Foo foo;
@Test
public void test() {
System.out.println(foo);
}
}
堆栈跟踪将类似于:
org.springframework.beans.factory.BeanCreationException: Could not inject field: com.tbp.Foo com.FooTest.foo; nested exception is java.lang.IllegalStateException: The field com.tbp.Foo com.FooTest.foo cannot have an existing value
at org.springframework.boot.test.mock.mockito.MockitoPostProcessor.inject(MockitoPostProcessor.java:413) ~[spring-boot-test-1.5.2.RELEASE.jar:1.5.2.RELEASE]
让我们以下面的例子为例。
@Autowired
@MockBean
private Foo foobar;
Spring 上下文是否先加载 class Foo
,然后再应用模拟?或者 @Mockbean
是否以某种方式被检测到,并且 Spring 创建并应用模拟而不是将 class Foo
加载到 Spring 上下文中。我怀疑是后者,但我想确认一下。
Spring会抛出异常。
让我们定义 class Foo.
@Component
public class Foo {
public Foo() {
System.out.println("I am not a mock");
}
}
每当使用 @Autowired
进行测试时,spring 都会注入一个 Foo 实例,并且构造函数将打印 "I am not a mock"
,如下面的代码所示。
@SpringBootTest(classes = Main.class)
@RunWith(SpringRunner.class)
public class FooTest {
@Autowired
Foo foo;
@Test
public void test() {
System.out.println(foo);
}
}
另一方面,使用@MockBean,spring不会创建真正的bean,也不会打印构造函数中的消息。此场景由以下代码表示。
@SpringBootTest(classes = Main.class)
@RunWith(SpringRunner.class)
public class FooTest {
@MockBean
Foo foo;
@Test
public void test() {
System.out.println(foo);
}
}
但是,当您尝试同时使用这两个注释时,spring 将抛出由 IllegalStateException
引起的 BeanCreationException
。这意味着字段 foo 不能具有现有值。这种情况会在执行下面的代码时发生:
@SpringBootTest(classes = Main.class)
@RunWith(SpringRunner.class)
public class FooTest {
// this will not work
@Autowired
@MockBean
Foo foo;
@Test
public void test() {
System.out.println(foo);
}
}
堆栈跟踪将类似于:
org.springframework.beans.factory.BeanCreationException: Could not inject field: com.tbp.Foo com.FooTest.foo; nested exception is java.lang.IllegalStateException: The field com.tbp.Foo com.FooTest.foo cannot have an existing value
at org.springframework.boot.test.mock.mockito.MockitoPostProcessor.inject(MockitoPostProcessor.java:413) ~[spring-boot-test-1.5.2.RELEASE.jar:1.5.2.RELEASE]