单元测试中如何通过@Autowired控制注入类?指定Baz实现类注入
解决Foo类单元测试中Autowired注入控制与Bar字段为null的问题
方案1:借助Spring Test上下文精准控制Bean注入
如果可以启动轻量的Spring测试上下文,直接指定要加载的Bean,让Spring自动处理注入逻辑:
@SpringBootTest @ContextConfiguration(classes = {Foo.class, Baz1.class}) public class FooTest { @Autowired private Foo foo; @MockBean // 用Mock替代真实Bar实例 private Bar bar; @Test void testFooBehavior() { // 配置Bar的Mock行为 when(bar.doSomething()).thenReturn("mockResult"); // 此时Foo中的List<Baz>仅包含Baz1实例,Bar字段也已被注入Mock对象 // 执行你的测试逻辑 } }
如果需要使用真实的Bar实例,把@MockBean换成@Autowired即可。
方案2:手动实例化+反射注入Bar
不想启动Spring上下文的话,手动构造Foo后,用反射给私有Bar字段赋值:
public class FooTest { @Test void testFoo() { // 只传入Baz1实例构造Foo Foo foo = new Foo(List.of(new Baz1())); // 创建Bar的Mock实例(或真实实例) Bar mockBar = Mockito.mock(Bar.class); // 用反射设置私有字段 try { Field barField = Foo.class.getDeclaredField("bar"); barField.setAccessible(true); barField.set(foo, mockBar); } catch (NoSuchFieldException | IllegalAccessException e) { throw new RuntimeException("注入Bar字段失败", e); } // 执行测试 } }
也可以用Spring Test的ReflectionTestUtils简化反射操作:
// 替换反射代码部分 ReflectionTestUtils.setField(foo, "bar", mockBar);
方案3:用Mockito的@InjectMocks自动注入
结合Mockito的注解简化注入流程,同时手动控制构造参数:
@ExtendWith(MockitoExtension.class) public class FooTest { @Mock private Bar bar; private Foo foo; @BeforeEach void setUp() { // 先构造仅包含Baz1的Foo foo = new Foo(List.of(new Baz1())); // 自动注入Bar字段 MockitoAnnotations.openMocks(this); ReflectionTestUtils.setField(foo, "bar", bar); } @Test void testFoo() { when(bar.someMethod()).thenReturn("testValue"); // 执行测试逻辑 } }
内容的提问来源于stack exchange,提问作者Frank Bao
相关产品推荐
相关产品推荐

