You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot集成Togglz测试时出现Could not find FeatureManager错误

问题根源

单元测试时Togglz的FeatureContext无法获取到FeatureManager,核心原因是:

  • 运行时Spring Boot会自动初始化Togglz上下文,但单元测试(尤其是非集成测试场景)中,完整的Web上下文或Togglz初始化逻辑未触发;
  • 你的FeatureOptions.isActive()直接依赖全局的FeatureContext.getFeatureManager(),测试环境下该上下文未被正确绑定。

解决方案

方案1:移除对FeatureContext的直接依赖(推荐)

既然控制器已经通过构造方法注入了FeatureManager,直接用它判断特性开关即可,完全绕开全局上下文的依赖:

修改控制器代码:

public class MyController {

  private final FeatureManager featureManager;

  public MyController(FeatureManager featureManager) {
    this.featureManager = featureManager;
  }

  public ResponseEntity<MyResponse> tempDriver(@RequestBody MyTempDriverRequest request) {
    // 直接用注入的featureManager判断特性状态
    if (featureManager.isActive(FeatureOptions.TEMP_DRIVER)) {
      if (request.getTempDriver().equals("")) {
        request.getTempDriver().setCountry("GB");
      }
    }
    // ...后续逻辑
  }
}

同时简化FeatureOptions枚举,去掉依赖全局上下文的方法:

public enum FeatureOptions implements Feature {
  @Label("Temporary driver")
  TEMP_DRIVER;
}

这种方式的优势:

  • 符合Spring依赖注入的设计原则,代码耦合度更低;
  • 测试时只需Mock或注入FeatureManager即可,无需处理全局上下文的初始化问题。

方案2:在单元测试中手动初始化Togglz上下文

如果必须保留FeatureOptions.isActive()的实现,需要在测试类中手动绑定FeatureManager到FeatureContext:

场景A:集成测试(使用@SpringBootTest)

确保测试类加载Togglz配置,并在测试前绑定上下文:

@SpringBootTest
@ContextConfiguration(classes = {TogglzConfiguration.class, MyController.class})
public class MtaControllerTest {

  @Autowired
  private FeatureManager featureManager;

  @BeforeEach
  void setUp() {
    // 将Spring管理的FeatureManager绑定到全局上下文
    FeatureContext.setFeatureManager(featureManager);
  }

  // 测试方法编写...
}

场景B:纯单元测试(使用Mockito)

不启动Spring上下文,手动创建或MockFeatureManager并绑定:

@RunWith(MockitoJUnitRunner.class)
public class MtaControllerTest {

  @Mock
  private FeatureManager featureManager;

  @InjectMocks
  private MyController myController;

  @BeforeEach
  void setUp() {
    // 方式1:手动创建FeatureManager并绑定
    FeatureManager testFeatureManager = new DefaultFeatureManager(
        new TogglzConfiguration(),
        new InMemoryStateRepository()
    );
    // 根据测试需求设置特性状态
    testFeatureManager.setFeatureState(new FeatureState(FeatureOptions.TEMP_DRIVER, true));
    FeatureContext.setFeatureManager(testFeatureManager);

    // 方式2:用Mockito Mock特性判断逻辑
    // when(featureManager.isActive(FeatureOptions.TEMP_DRIVER)).thenReturn(true);
  }

  // 测试方法编写...
}

额外注意事项

  • 确认TogglzConfiguration上的@Configuration注解生效,且所在包在Spring的扫描路径内;
  • 测试环境可通过@TestPropertySource指定单独的配置文件,确保Togglz特性开关符合测试预期;
  • 尽量避免在非Spring管理的代码中直接调用FeatureContext.getFeatureManager(),依赖注入的方式更利于测试和维护。

内容的提问来源于stack exchange,提问作者runnerpaul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 06:20:52