在Spring Context加载实际的Spring Bean之前,是否模拟了一个模拟bean(@MockBean)?

时间:2018-05-28 18:08:58

标签: spring spring-boot spring-test

让我们以下面的例子为例。

@Autowired
@MockBean
private Foo foobar;

Spring Context首先加载类Foo,然后应用模拟吗?或者以某种方式检测到@Mockbean,并且Spring创建并应用模拟而不是将类Foo加载到Spring上下文中。我怀疑它是后者,但我想要确认。

1 个答案:

答案 0 :(得分:3)

Spring会抛出异常。

让我们定义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将抛出由BeanCreationException引起的IllegalStateException。这意味着字段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]