编程语言
首页 > 编程语言> > java – 在测试中使用@MockBean强制重新加载Application Context

java – 在测试中使用@MockBean强制重新加载Application Context

作者:互联网

我在Spring Framework上运行了几个集成测试,扩展了名为BaseITCase的基类.
像这样:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {AppCacheConfiguration.class, TestConfiguration.class}, loader = SpringBootContextLoader.class)
@Transactional
@WebMvcTest
public abstract class BaseITCase{...}
...
public class UserControllerTest extends BaseITCase {...}

问题是其中一个测试有几个声明:
在它内部的@MockBean和执行此测试的那一刻,Spring重新创建了上下文,并且在此之后的测试有时会使用错误的bean(来自为@MockBean的测试创建的上下文).我通过检查bean有不同的哈希码来发现这一点.

当我使用@EventListener时,它变得非常关键.因为调用了错误上下文(已经完成执行的测试类的上下文)的侦听器,并且我在那里有错误的bean.

那有什么解决方法吗?

我试图将所有@MockBean声明移动到基本类,它工作正常,因为没有创建新的上下文.但是,它使基础课太重了.
此外,我尝试为此测试创建一个脏上下文,但接下来的测试失败,并显示上下文已被关闭的消息.

解决方法:

原因是具有@MockBean的测试的spring配置与其他测试不同,因此spring框架无法缓存以前使用的上下文并需要再次加载它.在这里您可以找到更详细的解释:https://github.com/spring-projects/spring-boot/issues/10015

正如您所说,如果您将模拟bean移动到父类,则不会重新加载上下文,这在bean配置保持不变时是有意义的.

一种可能的解决方法是将您的模拟bean定义为一个简单的模拟,并在需要的地方手动注入它.

例如,UserController依赖于Foo:

public class UserControllerTest extends BaseITCase {

    private Foo foo = Mockito.mock(Foo.class);

    @Autowired
    private UserController userController;

    @Before
    public void setUp() {
        super.setup();

        this.userController.setFoo(foo);
    }
}

@Component
public class UserController {

    private Foo foo;

    @Autowired
    public void setFoo(final Foo foo) {
        this.foo = foo;
    }
}

希望这可以帮助.

标签:java,spring,spring-test,mockito,springmockito
来源: https://codeday.me/bug/20190828/1750948.html