我有一个用 .NET 8 编写的 Azure 函数,它使用隔离的工作线程模型。 我想为此函数编写集成测试,因此想在内存中启动它。
我查看了
WebApplicationFactory
,但它似乎不支持隔离的工人模型。
我发现 Testcontainers
听起来很有希望(但这似乎也没有得到 100% 的支持)。但我正在尝试一下。为了实现这一点,我必须将我的功能进行docker化,这就是我面临问题的地方。我让 Visual Studio 生成了一个 Dockerfile。它可以构建,但是当使用图像启动容器时它会失败。
在深入了解错误的详细信息之前,请让我知道是否有其他方法可以解决此问题。我愿意接受建议。
值得注意的是,我使用以下命令从与 Dockerfile 不同的文件夹构建映像:
docker build -f "My Subfolder/Dockerfile" -t my-image:latest . --no-cache
。
注释掉的行是我尝试过的其他内容:
FROM mcr.microsoft.com/azure-functions/dotnet-isolated:4-dotnet-isolated8.0 AS base
#COPY --from=mcr.microsoft.com/dotnet/core/sdk:3.1 /usr/share/dotnet /usr/share/dotnet
WORKDIR /home/site/wwwroot
EXPOSE 8080
# Install Azure Functions Core Tools
RUN apt-get update && \
apt-get install -y curl && \
curl -sL https://deb.nodesource.com/setup_20.x | bash - && \
apt-get install -y nodejs && \
npm install -g azure-functions-core-tools@4 --unsafe-perm
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY . .
RUN dotnet restore "./My Subfolder/Project.csproj"
#COPY . .
WORKDIR "/src/My Subfolder"
#RUN dotnet build "./Project.csproj" -c $BUILD_CONFIGURATION -o /app/build
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./Project.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /home/site/wwwroot
COPY --from=publish /app/publish .
#RUN apt-get update && \
# apt-get install -y nodejs npm && \
# npm install -g azurite
#CMD ["ls"]
ENTRYPOINT ["func", "start", "--dotnet-isolated"]
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
AzureFunctionsJobHost__Logging__Console__IsEnabled=true \
WEBSITES_INCLUDE_CLOUD_CERTS=true
一个错误似乎是该函数需要一个它无权访问的存储帐户。 一种想法是在容器中安装 Azurite,但我并没有真正让它发挥作用,因为我有多个以类似方式设置的 Azure 函数,它们都有自己的安装。
另一种方法是使用 docker compose,但 .NET 版本的 Testcontainers 尚不支持。 因此,为了继续前进,我删除了需要存储的部分(TimerTrigger),因此错误暂时消失了。
另一个非常持久的错误是它似乎无法读取我的
settings.json
文件。我使用选项模式进行一些验证,例如:
public sealed class MyOptions
{
[Required(ErrorMessage = "Option is required")]
public string SomeOption { get; set; } = null!;
}
我在 Dockerfile 的最后阶段尝试了
CMD ["ls"]
,它确实列出了我的 settings.json
文件。它在本地运行良好,所以不确定这里发生了什么。
错误看起来像这样:
2024-09-23 12:17:07 Azure Functions Core Tools
2024-09-23 12:17:07 Core Tools Version: 4.0.6280 Commit hash: N/A +421f0144b42047aa289ce691dc6db4fc8b6143e6 (64-bit)
2024-09-23 12:17:07 Function Runtime Version: 4.834.3.22875
2024-09-23 12:17:07
2024-09-23 12:17:08 [2024-09-23T10:17:08.173Z] Csproj not found in /home/site/wwwroot directory tree. Skipping user secrets file configuration.
2024-09-23 12:17:08 Skipping 'AzureWebJobsScriptRoot' from local settings as it's already defined in current environment variables.
2024-09-23 12:17:08 Skipping 'AZURE_FUNCTIONS_ENVIRONMENT' from local settings as it's already defined in current environment variables.
2024-09-23 12:17:09
2024-09-23 12:17:09 Functions:
2024-09-23 12:17:09
2024-09-23 12:17:09 MyHttpFunction: [GET,POST] http://localhost:7071/api/MyHttpFunction
2024-09-23 12:17:09
2024-09-23 12:17:09 For detailed output, run func with --verbose flag.
2024-09-23 12:17:09 [2024-09-23T10:17:09.841Z] MyOptions:
2024-09-23 12:17:10 [2024-09-23T10:17:10.154Z] Unhandled exception. Microsoft.Extensions.Options.OptionsValidationException: DataAnnotation validation failed for 'MyOptions' members: 'SomeOption' with the error: 'Option is required'.
2024-09-23 12:17:10 [2024-09-23T10:17:10.154Z] at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
2024-09-23 12:17:10 [2024-09-23T10:17:10.154Z] at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
2024-09-23 12:17:10 [2024-09-23T10:17:10.154Z] at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
2024-09-23 12:17:10 [2024-09-23T10:17:10.154Z] at System.Lazy`1.CreateValue()
2024-09-23 12:17:10 [2024-09-23T10:17:10.154Z] at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd[TArg](String name, Func`3 createOptions, TArg factoryArgument)
...
不同的方法:是否有不同的方法来解决这个问题?我愿意接受建议。
存储帐户:如何处理 Docker 容器中的存储帐户要求?安装 Azurite 是正确的方法吗?
Settings.json:为什么我的settings.json 文件在 Docker 容器中无法正确读取,如何解决这个问题?
我不知道如何继续。我不确定我是否走在 Testcontainers 和 Docker 的正确轨道上。我愿意接受有关如何解决这些问题的建议。我也愿意接受其他方法,使用隔离的 worder 模型为我的 Azure Function 编写集成测试。
对于隔离的工作模型功能,
AzureFunctions.TestHost
库提供了无需 Docker 的本地测试选项。
Azurite 仍然是模拟 Azure 存储的最佳解决方案之一。但是,为了使其顺利运行,请使用 Docker Compose 同时运行函数应用程序和 Azurite,
Docker 撰写:
version: '3.8'
services:
functionapp:
image: my-azure-function-app:latest
build:
context: .
dockerfile: Dockerfile
ports:
- "7071:8080"
environment:
AzureWebJobsStorage: "UseDevelopmentStorage=true"
depends_on:
- azurite
azurite:
image: mcr.microsoft.com/azure-storage/azurite
ports:
- "10000:10000"
日志:
Azure Functions Core Tools
Core Tools Version: 4.0.6280 Commit hash: N/A +421f0144b42047aa289ce691dc6db4fc8b6143e6 (64-bit)
Function Runtime Version: 4.834.3.22875
[2024-09-23T10:17:08.173Z] Csproj not found in /home/site/wwwroot directory tree. Skipping user secrets file configuration.
Skipping 'AzureWebJobsScriptRoot' from local settings as it's already defined in current environment variables.
Skipping 'AZURE_FUNCTIONS_ENVIRONMENT' from local settings as it's already defined in current environment variables.
Functions:
MyHttpFunction: [GET,POST] http://localhost:7071/api/MyHttpFunction
For detailed output, run func with --verbose flag.
[2024-09-23T10:17:09.841Z] MyOptions:
[2024-09-23T10:17:10.154Z] Unhandled exception. Microsoft.Extensions.Options.OptionsValidationException: DataAnnotation validation failed for 'MyOptions' members: 'SomeOption' with the error: 'Option is required'.
at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
at System.Lazy`1.CreateValue()
at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd[TArg](String name, Func`3 createOptions, TArg factoryArgument)