spring-boot - Bean 在 Spring Boot 中没有被覆盖
问题描述
我正在尝试按照本教程编写和测试一个使用带有 azure 函数的 spring-cloud 的应用程序。 https://github.com/markusgulden/aws-tutorials/tree/master/spring-cloud-function/spring-cloud-function-azure/src/main/java/de/margul/awstutorials/springcloudfunction/azure
我正在尝试编写一个测试用例并覆盖 bean。这是具有函数和处理程序 Bean 函数的应用程序类。
@SpringBootApplication
@ComponentScan(basePackages = { "com.package" })
public class DataFunctions extends AzureSpringBootRequestHandler<GenericMessage<Optional<String>>, Data> {
@FunctionName("addData")
public HttpResponseMessage addDataRun(
@HttpTrigger(name = "add", methods = {
HttpMethod.POST }, authLevel = AuthorizationLevel.FUNCTION) HttpRequestMessage<Optional<String>> request,
final ExecutionContext context) throws JsonParseException, JsonMappingException, IOException {
context.getLogger().info("Java HTTP trigger processed a POST request.");
try {
handleRequest(new GenericMessage<Optional<String>>(request.getBody()), context);
} catch (ServiceException ex) {
ErrorMessage em = new ErrorMessage();
return request.createResponseBuilder(handleException(ex, em)).body(em).build();
}
return request.createResponseBuilder(HttpStatus.CREATED).build();
}
@Autowired
MyService mService;
@Bean
public Consumer<GenericMessage<Optional<String>>> addData() {
ObjectMapper mapper = new ObjectMapper();
return req -> {
SomeModel fp = null;
try {
fp = mapper.readValue(req.getPayload().get(), SomeModel.class);
} catch (Exception e) {
throw new ServiceException(e);
}
mService.addData(fp);
};
}
}
我想通过覆盖上面的bean来进行测试。
Cosmosdb 弹簧配置
@Configuration
@EnableDocumentDbRepositories
public class CosmosDBConfig extends AbstractDocumentDbConfiguration {
@Value("${cosmosdb.collection.endpoint}")
private String uri;
@Value("${cosmosdb.collection.key}")
private String key;
@Value("${cosmosdb.collection.dbname}")
private String dbName;
@Value("${cosmosdb.connect.directly}")
private Boolean connectDirectly;
@Override
public DocumentDBConfig getConfig() {
ConnectionPolicy cp = ConnectionPolicy.GetDefault();
if (connectDirectly) {
cp.setConnectionMode(ConnectionMode.DirectHttps);
} else {
cp.setConnectionMode(ConnectionMode.Gateway);
}
return DocumentDBConfig.builder(uri, key, dbName).connectionPolicy(cp).build();
}
}
这是配置
@TestConfiguration
@PropertySource(value = "classpath:application.properties", encoding = "UTF-8")
@Profile("test")
@Import({DataFunctions.class})
public class TestConfig {
@Bean(name="addData")
@Primary
public Consumer<GenericMessage<Optional<String>>> addData() {
return req -> {
System.out.println("data mock");
};
}
@Bean
@Primary
public DocumentDBConfig getConfig() {
return Mockito.mock(DocumentDBConfig.class);
}
}
最后是测试课
@RunWith(SpringRunner.class)
//@SpringBootTest //Enabling this gives initialization error.
@ActiveProfiles("test")
public class TempTest {
@InjectMocks
DataFunctions func;
@Mock
MyService mService;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
private Optional<String> createRequestString(final String res) throws IOException {
InputStream iStream = TempTest.class.getResourceAsStream(res);
String charset="UTF-8";
try (BufferedReader br = new BufferedReader(new InputStreamReader(iStream, charset))) {
return Optional.of(br.lines().collect(Collectors.joining(System.lineSeparator())));
}
}
@Test
public void testHttpPostTriggerJava() throws Exception {
@SuppressWarnings("unchecked")
final HttpRequestMessage<Optional<String>> req = mock(HttpRequestMessage.class);
final Optional<String> queryBody = createRequestString("/test-data.json");
doNothing().when(mService).addData(Mockito.any(SomeModel.class));
doReturn(queryBody).when(req).getBody();
doAnswer(new Answer<HttpResponseMessage.Builder>() {
@Override
public HttpResponseMessage.Builder answer(InvocationOnMock invocation) {
HttpStatus status = (HttpStatus) invocation.getArguments()[0];
return new HttpResponseMessageMock.HttpResponseMessageBuilderMock().status(status);
}
}).when(req).createResponseBuilder(any(HttpStatus.class));
final ExecutionContext context = mock(ExecutionContext.class);
doReturn(Logger.getGlobal()).when(context).getLogger();
doReturn("addData").when(context).getFunctionName();
// Invoke
final HttpResponseMessage ret = func.addDataRun(req, context);
// Verify
assertEquals(ret.getStatus(), HttpStatus.CREATED);
}
}
对于这种情况,而不是测试配置addData
,实际的 bean 是从 DataFunctions 类调用的。此外,当它应该使用我的测试配置中的模拟 bean 时,也会创建数据库连接。有人可以指出我的测试配置有什么问题吗?
解决方案
我能够通过标记它来解决 cosmos db 配置加载的第一部分
@Configuration
@EnableDocumentDbRepositories
@Profile("!test")
public class CosmosDBConfig extends AbstractDocumentDbConfiguration {
...
}
还必须在服务中将存储库 bean 标记为可选。
public class MyService {
@Autowired(required = false)
private MyRepository myRepo;
}
没有使用除此之外的任何弹簧引导配置。
@ActiveProfiles("test")
public class FunctionTest {
...
}
对于提供 Mock 处理程序的模拟版本的第二部分,我只是将测试配置文件制作为 Spring 应用程序,如下所示。
@SpringBootApplication
@ComponentScan(basePackages = { "com.boeing.da.helix.utm.traffic" })
@Profile("test")
public class TestConfiguration {
public static void main(final String[] args) {
SpringApplication.run(TestConfiguration.class, args);
}
@Bean(name="addData")
@Primary
public Consumer<GenericMessage<Optional<String>>> addData() {
return req -> {
System.out.println("data mock");
};
}
}
并在我的构造函数中使用了 spring cloud 中的 azure 函数库中的这个构造函数
public class AppFunctions
extends AzureSpringBootRequestHandler<GenericMessage<Optional<String>>, List<Data>> {
public AppFunctions(Class<?> configurationClass) {
super(configurationClass);
}
}
public AzureSpringBootRequestHandler(Class<?> configurationClass) {
super(configurationClass);
}
希望它可以帮助某人。
推荐阅读
- ios - 如何使我的单元格像 App Store 中一样圆润
- ebay-api - eBay API findItemsAdvanced 调用返回“项目过滤器需要值,条件
- lua - “PlayerAdded”脚本甚至在玩家死后仍然有效。怎么修?
- scala - Scala spark,显示不同的列值和计数出现次数
- algorithm - 找到滑动窗口中的最大数
- javascript - 如何对过滤后的 html 表求和?
- flutter - 如何在flutter中制作排行榜?
- r - predict.glm() 函数中的“s”参数是什么?
- c# - WebApi2:路由与查询字符串
- css - Ionic 4 中的 CSS 自定义属性:背景悬停