【问题标题】:Init spring boot mocks before they are injected在注入之前初始化弹簧靴模拟
【发布时间】:2021-01-26 15:01:11
【问题描述】:

有没有办法在将模拟注入另一个组件之前对其进行初始化?

举个例子,我有以下课程:

@Service
SomeService {
    @Autowired
    public SomeService(SomeConfig config)
}

@Configuration
@Getter
@Setter
public class SomeConfig {
  private String someValue;
}

在我的测试中,我正在执行以下操作:

@MockBean
SomeConfig someConfig;

@Autowired
SomeService someService;

问题是,SomeService 构造函数已经在访问 SomeConfig 成员,而我什至无法使用 when(someConfig.getSomeValue()).thenReturn("something") 对其进行初始化,从而导致 NullPtrException

SomeService 被实例化之前是否有一个钩子被执行?

【问题讨论】:

  • 在你的测试中你不应该在SomeService 上做@InjectMocks 而不是@Autowired吗?
  • 您能否提供您的测试方法,以便我们对您要测试的内容有更多的了解?

标签: java spring spring-boot junit mockito


【解决方案1】:

您可以在设置方法中手动设置您的服务。
只需确保在这些测试中从类路径扫描中排除您的 SomeService 即可。

SomeServiceTest {
  @MockBean
  SomeConfig someConfig;

  SomeService someService;

  @BeforeEach
  public void setup(){
    // init mocks
    // setup other stuff

    someService = new SomeService(someConfig);
  }

}

【讨论】:

  • 这就是我现在正在做的,但我想知道是否有更优雅的方式。
  • 另一种方法是定义一个包含(模拟)bean 的 TestConfig 类。然后,您可以将该 TestConfig 导入您的测试上下文中。但我不认为这是一种更优雅的方式。但取决于您的测试。
【解决方案2】:

我假设 SomeService 看起来像:

@Service
SomeService {

    private final SomeConfig config

    @Autowired
    public SomeService(SomeConfig config) {
       this.someConfig = someConfig;
       // some logic with config getters
    }
}

你应该使用注解 @PostConsturct 在一个单独的方法中,并将配置 getter 的使用放在那里,例如:

@PostConstruct
private void postConstruct() {
// some logic with config getters
}

【讨论】:

  • 我希望在不更改生产代码的情况下实现这一目标,但这听起来是一个不错的解决方案。会试一试的。
猜你喜欢
  • 2018-11-22
  • 2021-11-11
  • 2018-07-18
  • 2017-12-22
  • 2017-10-14
  • 1970-01-01
  • 1970-01-01
  • 2012-03-01
  • 1970-01-01
相关资源
最近更新 更多