测试 Spring bean 时模拟配置属性

问题描述

我有一个application.yml 读取配置属性值的 Spring bean

public class AutodisableRolesService {

    @Value("${cron.enabled}")
    private boolean runTask;
    // remainder of class omitted
}

在 application.yml 中此属性设置为 false

cron:
  enabled: false

但是当我运行测试时,我希望它是真的。我尝试了以下方法,但似乎不起作用

@SpringBoottest(properties = { "cron.enabled=true" })
@ExtendWith(MockitoExtension.class)
public class AutodisableRolesServiceTests {
    
    @Mock
    private UserRoleRepository userRoleRepository;

    @InjectMocks
    private AutodisableRolesService autodisableRolesService;
    // remainder of test class omitted
}

我也尝试了以下方法,但没有成功

@ContextConfiguration(classes = AutodisableRolesService.class)
@TestPropertySource(properties = "cron.enabled=true")
@ExtendWith(MockitoExtension.class)
public class AutodisableRolesServiceTests {

    @Mock
    private UserRoleRepository userRoleRepository;

    @InjectMocks
    private AutodisableRolesService autodisableRolesService;
    // remainder of test class omitted
}

解决方法

您混淆了两种类型的测试设置;带有 Mockito 测试设置的 Spring 启动测试设置。通过在被测类上使用 @InjectMocks,Mockito 实例化该类并注入所有用 @Mock 注释的字段,绕过 Spring TestApplicationContext 设置。

或者使用 Spring 测试设置:

@SpringBootTest(properties = { "cron.enabled=true" })
public class AutoDisableRolesServiceTests {
    
    @MockBean
    private UserRoleRepository userRoleRepository;

    @Autowired
    private AutoDisableRolesService autoDisableRolesService;

    // remainder of test class omitted
}

或使用以下方法设置的 mockito:

public class AutoDisableRolesServiceTests {
    
    @Mock
    private UserRoleRepository userRoleRepository;

    @InjectMocks
    private AutoDisableRolesService autoDisableRolesService;

    @BeforeEach
    public void setUp() {
        ReflectionTestUtils.setField(autoDisableRolesService,"runTask",true);
    }
}

[编辑]

如果您不需要完整的@SpringBootTest 设置,请使用

@ExtendWith(SpringExtension.class)
@TestPropertySource(properties={"cron.enabled=true"})
@ContextConfiguration(classes = { AutoDisableRolesService.class})
public class AutoDisableRolesServiceTests {
    
    @MockBean
    private UserRoleRepository userRoleRepository;

    @Autowired
    private AutoDisableRolesService autoDisableRolesService;

    // remainder of test class omitted
}

@SpringBootTest 和@ExtendsWith(SpringExtension.class) 的区别在于@SpringBootTest 加载完整的(测试)ApplicationContext,而后者只加载部分上下文,速度更快但不包括所有内容。