我可以使用Xunit这样测试我的Azure Function:
var req = GenerateReq();
var res = await MyFunc.Run(req, logger);
如果在我的函数中,我像这样生成一个CosmosDb DocumentClient:
static DocumentClient docClient = GetCustomClient();
private static DocumentClient GetCustomClient()
{
string cosmosUrl = string.Empty;
string cosmosKey = string.Empty;
cosmosUrl = Environment.GetEnvironmentVariable("cosmosUrl");
cosmosKey = Environment.GetEnvironmentVariable("cosmosKey");
DocumentClient customClient = new DocumentClient(new Uri(cosmosUrl), cosmosKey,
new ConnectionPolicy
{
ConnectionMode = ConnectionMode.Direct,
ConnectionProtocol = Protocol.Tcp,
// Customize retry options for Throttled requests
RetryOptions = new RetryOptions()
{
MaxRetryAttemptsOnThrottledRequests = 10,
MaxRetryWaitTimeInSeconds = 30
}
});
return customClient;
}
当我尝试访问docClient时,出现异常:
The type initializer for 'MyFunc.Get' threw an exception.
是否有解决此问题的方法?
答案 0 :(得分:1)
您可以通过使用启动类并设置依赖项注入来解决此问题。然后,可以生成其使用的IDocumentClient接口,而不是生成DocumentClient。从那里,您可以在测试期间模拟IDocumentClient。
我写过有关设置启动类here
的文章答案 1 :(得分:1)
这可能是由于错误的静态构造函数或错误的静态属性/字段的内联初始化引起的。例如:
class MyFunc
{
static MyFunc()
{
//buggy code here
}
static DocumentClient docClient = Buggy_GetCustomClient(); // <-- or here
}
以上将在第一次使用TypeInitializationException
之前引起MyFunc
。
运行该代码时是否定义了环境变量cosmosUrl
和cosmosKey
?如果不是,则可能是原因。 GetCustomClient
最终将引发异常,并将其包装在TypeInitializationException
中。
如Napoloeon的回答中所建议,我建议使用依赖注入来获取IDocumentClient
的实例(假设您正在使用函数v2)。看一下这个answer,它显示了如何在Azure Functions v2中注入和使用IDocumentClient
。 Azure函数的DI支持的正式文档为here。
答案 2 :(得分:1)
您肯定应该使用依赖注入来解决此问题。当前,您将在单元测试中使用实际的DocumentClient
,这是一个不好的做法-您应该使用DocumentClient
的 mock ,以便您控制行为。 / p>
如here所述,创建一个Startup.cs文件并注册您的客户端:
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
[assembly: FunctionsStartup(typeof(MyApp.Startup))]
namespace MyApp
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
IDocumentClient client = GetCustomClient();
builder.Services.AddSingleton<IDocumentClient>(client);
}
private static DocumentClient GetCustomClient()
{
string cosmosUrl = Environment.GetEnvironmentVariable("cosmosUrl");
string cosmosKey = Environment.GetEnvironmentVariable("cosmosKey");
DocumentClient customClient = new DocumentClient(new Uri(cosmosUrl), cosmosKey, new ConnectionPolicy
{
ConnectionMode = ConnectionMode.Direct,
ConnectionProtocol = Protocol.Tcp,
// Customize retry options for Throttled requests
RetryOptions = new RetryOptions()
{
MaxRetryAttemptsOnThrottledRequests = 10,
MaxRetryWaitTimeInSeconds = 30
}
});
return customClient;
}
}
}
然后,您可以在函数中插入IDocumentClient
作为输入绑定:
[CosmosDB("DatabaseName", "CollectionName")] IDocumentClient documentClient
在单元测试中,您可以使用Moq之类的库来模拟IDocumentClient
。
private Mock<IDocumentClient> _mockDocumentClient = new Mock<IDocumentClient>();
var req = GenerateReq();
var res = await MyFunc.Run(req, logger, _mockDocumentClient.Object);