[英]Best practices for Spring boot testing against authenticated remote system
我编写了利用Azure SDK 的代码,以便与 Blob 存储交互。
作为一名聪明而尽职的开发人员,我没有通过导航实时应用程序来测试我的代码,而是创建了一个 Spring Boot JUnit 测试并花了几个小时来修复我所有的错误。 事实上,我没有使用任何类型的 mocking,因为我的问题是以正确的方式使用库。 我针对 blob 存储的实时实例运行代码,并检查我的所有 Java 方法是否按预期工作。
我写在这里是因为
我从一开始就知道将凭据硬编码到代码中是最糟糕的做法,但从今天早上开始我想专注于我的任务。 现在我想采用最佳实践。 我问的是重新设计测试结构
测试代码是这样的。
该代码创建一个临时容器并尝试存储/检索/删除 blob。 它使用 GUID 创建一个唯一的私有工作区,在测试完成后清除。
@SpringBootTest(classes = FileRepositoryServiceAzureBlobImplTest.class)
@SpringBootConfiguration
@TestConfiguration
@TestPropertySource(properties = {
"azure-storage-container-name:amlcbackendjunit",
"azure-storage-connection-string:[not going to post it on Stackoverflow before rotating it]"
})
class FileRepositoryServiceAzureBlobImplTest {
private static final Resource LOREM_IPSUM = new ClassPathResource("loremipsum.txt", FileRepositoryServiceAzureBlobImplTest.class);
private FileRepositoryServiceAzureBlobImpl uut;
private BlobContainerClient blobContainerClient;
private String loremChecksum;
@Value("${azure-storage-connection-string}")
private String azureConnectionString;
@Value("${azure-storage-container-name}")
private String azureContainerName;
@BeforeEach
void beforeEach() throws IOException {
String containerName = azureContainerName + "-" + UUID.randomUUID();
blobContainerClient = new BlobContainerClientBuilder()
.httpLogOptions(new HttpLogOptions().setApplicationId("az-sp-sb-aml"))
.clientOptions(new ClientOptions().setApplicationId("az-sp-sb-aml"))
.connectionString(azureConnectionString)
.containerName(containerName)
.buildClient()
;
blobContainerClient.create();
uut = spy(new FileRepositoryServiceAzureBlobImpl(blobContainerClient));
try (InputStream loremIpsumInputStream = LOREM_IPSUM.getInputStream();) {
loremChecksum = DigestUtils.sha256Hex(loremIpsumInputStream);
}
blobContainerClient
.getBlobClient("fox.txt")
.upload(BinaryData.fromString("The quick brown fox jumps over the lazy dog"));
}
@AfterEach
void afterEach() throws IOException {
blobContainerClient
.delete();
}
@Test
void store_ok() {
String desiredFileName = "loremIpsum.txt";
FileItemDescriptor output = assertDoesNotThrow(() -> uut.store(LOREM_IPSUM, desiredFileName));
assertAll(
() -> assertThat(output, is(notNullValue())),
() -> assertThat(output, hasProperty("uri", hasToString(Matchers.startsWith("azure-blob://")))),
() -> assertThat(output, hasProperty("size", equalTo(LOREM_IPSUM.contentLength()))),
() -> assertThat(output, hasProperty("checksum", equalTo(loremChecksum))),
() -> {
String localPart = substringAfter(output.getUri().toString(), "azure-blob://");
assertAll(
() -> assertTrue(blobContainerClient.getBlobClient(localPart).exists())
);
}
);
}
}
在生产中(也包括在 SIT/UAT 中),真正的 Spring Boot 应用程序将从 Container 环境中获取配置,包括存储连接字符串。 是的,对于这种测试,我也可以避免使用 Spring 和@TestPropertySource
,因为我没有利用上下文中的任何 bean。
我想问一下如何修改这个测试以便
这是由测试组成的构建作业
- task: Gradle@2
displayName: Build with Gradle
inputs:
gradleWrapperFile: gradlew
gradleOptions: -Xmx3072m $(gradleJavaProperties)
options: -Pci=true -PbuildId=$(Build.BuildId) -PreleaseType=${{parameters.releaseType}}
jdkVersionOption: 1.11
jdkArchitectureOption: x64
publishJUnitResults: true
sqAnalysisEnabled: true
sqGradlePluginVersionChoice: specify
sqGradlePluginVersion: 3.2.0
testResultsFiles: '$(System.DefaultWorkingDirectory)/build/test-results/**/TEST-*.xml'
tasks: clean build
注 1:实时应用程序可以在没有存储连接字符串的情况下启动。 它回退到本地临时目录。
答案解释起来有点复杂,所以我尽力了
请注意,如果您尝试使用我使用的确切键重新创建示例,则原始变量名称和 YMMV 已被编辑
示例名称testStorageAccountConnectionString
- task: Gradle@3
displayName: Build with Gradle
inputs:
gradleWrapperFile: gradlew
gradleOptions: -Xmx10240m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -DAZURE_STORAGE_CONNECTION_STRING=$(AZURE_STORAGE_CONNECTION_STRING)
options: --build-cache -Pci=true -PgitCommitId=$(Build.SourceVersion) -PbuildId=$(Build.BuildId) -Preckon.stage=${{parameters.versionStage}} -Preckon.scope=${{parameters.versionScope}}
jdkVersionOption: 1.11
jdkArchitectureOption: x64
publishJUnitResults: true
sqAnalysisEnabled: true
sqGradlePluginVersionChoice: specify
sqGradlePluginVersion: 3.2.0
testResultsFiles: '$(System.DefaultWorkingDirectory)/build/test-results/**/TEST-*.xml'
tasks: clean build
env:
AZURE_STORAGE_CONNECTION_STRING: $(testStorageAccountConnectionString)
AZURE_STORAGE_CONNECTION_STRING
接受占位符${azure.storageConnectionString}
。 请阅读文档并先在本地尝试。 这意味着我们需要使用适当设置的环境变量来运行测试,以解析占位符-D
运行加个环境变量。 -DAZURE_STORAGE_CONNECTION_STRING=$(AZURE_STORAGE_CONNECTION_STRING)
将环境变量AZURE_STORAGE_CONNECTION_STRING
添加到测试运行中,等于管道环境变量AZURE_STORAGE_CONNECTION_STRING
(不是那个幻想) Gradle 的env属性为管道容器设置环境变量。 在这种情况下,我们确保 Gradle 在AZURE_STORAGE_CONNECTION_STRING
设置为testStorageAccountConnectionString
的情况下运行。 Env 是 Azure 管道代理解析和释放秘密变量内容的唯一地方
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.