将一个 MockBean 注入另一个 MockBean

Injecting one MockBean into another

我有一个典型的 SpringApplication,我正在尝试通过 MockMvc 对其进行测试。该应用程序包含一些数据库调用和一些第三方 api 调用,我想模拟所有这些调用,同时测试端到端流程,第三方

除外

这是我创建的 -

控制器class

public class PortfolioController {

private final PortfolioService portfolioService;
}

服务Class

public class PortfolioService {

private final PortfolioTransactionRepository portfolioTransactionRepository;
private final AlphavantageService alphavantageService;
}

AlphaVantageService

public class AlphavantageService {

private ApiConfig apiConfig;

private final RestTemplate restTemplate;

public Map<String, List<Candle>> getStockQuotes(List<String> symbols) {
    return symbols.stream().collect(Collectors.toMap(symbol -> symbol, symbol -> getQuotes(symbol)));
}
}

考验来了-

@ExtendWith(SpringExtension.class)
@WebMvcTest(controllers = PortfolioController.class)
class PortfolioControllerTest {

private List<PortfolioTransaction> transactions;

@MockBean
private AlphavantageService alphavantageService;

@MockBean
private PortfolioService portfolioService;

@Autowired
private PortfolioController portfolioController;

@Autowired
private MockMvc mockMvc;
}

问题是,当我尝试在服务器上执行任何 mvc 调用时,AlphaVantageService 没有注入到 PortfolioService 中,所以直到第 1 级,我得到了 bean 注入,但在更深层次上,我不明白。

是设计使然还是我遗漏了什么?我们应该如何测试这样的测试用例?

实际上,在尝试了一些选项之后,我找到了解决方案。

就像@MockBean一样,spring也有一个概念叫做@SpyBean。那解决了我的问题。所以现在我的测试如下所示

@ExtendWith(SpringExtension.class)
@WebMvcTest(controllers = PortfolioController.class)
@MockBeans(value = {@MockBean(AlphavantageService.class), 
@MockBean(PortfolioTransactionRepository.class)})
@SpyBeans(value = {@SpyBean(PortfolioService.class)})
class PortfolioControllerTest {

private List<PortfolioTransaction> transactions;

@Autowired
private AlphavantageService alphavantageService;

@Autowired
@SpyBean
private PortfolioService portfolioService;

@Autowired
private PortfolioController portfolioController;

@Autowired
private MockMvc mockMvc;
}

这很有用,我可以在测试中使用完整的依赖注入。