模拟自动连线字段in@Import类



我正在做一个单元测试,它需要一些由弹簧注入的对象,所以我使用:

@RunWith(SpringRunner.class)
@Import({BConfig.class})
public class ATest {
private A a;
@Autowired
private B b;
@Before
public void init() {
a = new A(b);
}
}

但是,BConfig 类有一个自动连线字段 c,我在此测试中不需要它:

class BConfig {
@Autowired
C c;
@Bean
public getB() {
return new B();
}
// other method code will use field c
}

自动连线的 c 字段将从 @PostConstruct 中的 redis 获取单元测试中不存在的数据。如果我不省略,单元测试将报告由于 redis 数据不存在而导致的错误。

我有一个解决方案,可以将 C 到 2 个子类 CProduction 和 CUnitTest 它们都实现了接口 C,然后活动配置文件以在单元测试中使用 CUnitTest。然而,这是某种侵入性的,因为如果不做单元测试,C 的接口就毫无用处。

有没有更好的方法可以做到这一点?

考虑使用:

@RunWith(SpringRunner.class)
@ContextConfiguration({BConfig.class})
class ATest {
@MockBean // will place a mock implementation of C to the context instead of real one that tries to connect with Redis.
C c;
...
}

请注意,如果 C 是接口,它将无缝工作。否则,它将尝试通过继承(从 C 扩展的内容(创建一个代理,如果 C 在构造函数中有一些与 redis 相关的代码,它可能仍然会尝试调用它。

更新 1

根据OP的评论,试图澄清答案:

当 spring 应用程序上下文启动时,它基本上解析了所有 bean 并注入了所需的内容。

首先,它解析 bean 定义(元数据( - 实际类、作用域等。 然后它按照允许注射的顺序创建豆子。例如,它类 A 有一个类 B 的字段(两者都是 bean(,那么 spring 必须首先创建 B,然后创建 A 并将 B 注入 A 中。

现在,@MockBean是一个与测试相关的钩子。它告诉测试中使用的 spring 应用程序上下文,而不是常规的 bean 定义,即 spring 能够从@Configuration类中解析出来或由于放置在其上的注释而找到组件@Component它应该使用 Mock - 在运行时使用 Mockito 等框架生成的东西。

这个模拟实现稍后可以用来指定期望(参见 Mockito 基本教程,互联网上有很多这样的教程(,但对于你的情况来说更重要的是,它不会连接到 redis,因为这个模拟实现没有任何与 redis 相关的代码。

更新 2

应按如下方式重写配置:

@Configuration
public class BConfig {
@Bean
public getB() {
return new B();
}
@Bean
public C c() {
return new C();
}

// other method code will use field c:
// if for example D uses C: then you can:
@Bean
public D d(C c) {
return new D(c);
} 
}

最新更新