Dav*_*rin 7 c# moq xunit azure
我在使用 Moq 和 xUnit 在 C# 中编写单元测试时遇到问题。
在我的服务中,我有以下代码:
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret, options);
var graphClient = new GraphServiceClient(clientSecretCredential);
return (await graphClient.Users.Request().Filter($"displayName eq '{mobilePhone}'").GetAsync()).FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)
但我不知道模拟该函数的方法GraphClient:
graphClient.Users.Request().Filter($"displayName eq '{mobilePhone}'").GetAsync()).FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)
Oli*_*ver 14
将 Graph SDK 升级到 v5 后,模拟服务客户端的方式已发生变化,并且并没有变得更容易。有多种不同的方法可供选择,本期列出了其中的一些方法。我目前的模拟方法是这样的:
public static class RequestAdapterMockFactory
{
public static Mock<IRequestAdapter> Create(MockBehavior mockBehavior = MockBehavior.Strict)
{
var mockSerializationWriterFactory = new Mock<ISerializationWriterFactory>();
mockSerializationWriterFactory.Setup(factory => factory.GetSerializationWriter(It.IsAny<string>()))
.Returns((string _) => new JsonSerializationWriter());
var mockRequestAdapter = new Mock<IRequestAdapter>(mockBehavior);
// The first path element must have four characters to mimic v1.0 or beta
// This is especially needed to mock batch requests.
mockRequestAdapter.SetupGet(adapter => adapter.BaseUrl).Returns("http://graph.test.internal/mock");
mockRequestAdapter.SetupSet(adapter => adapter.BaseUrl = It.IsAny<string>());
mockRequestAdapter.Setup(adapter => adapter.EnableBackingStore(It.IsAny<IBackingStoreFactory>()));
mockRequestAdapter.SetupGet(adapter => adapter.SerializationWriterFactory).Returns(mockSerializationWriterFactory.Object);
return mockRequestAdapter;
}
}
var mockRequestAdapter = RequestAdapterMockFactory.Create();
var graphServiceClient = new GraphServiceClient(mockRequestAdapter.Object);
mockRequestAdapter.Setup(adapter => adapter.SendAsync(
// Needs to be correct HTTP Method of the desired method
It.Is<RequestInformation>(info => info.HttpMethod == Method.GET),
// Needs to be method from object type that will be returned from the SDK method.
Microsoft.Graph.Models.User.CreateFromDiscriminatorValue,
It.IsAny<Dictionary<string, ParsableFactory<IParsable>>>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new Microsoft.Graph.Models.User
{
DisplayName = "Hello World",
});
Run Code Online (Sandbox Code Playgroud)
这种方法相当臃肿,但我没有找到适合我的情况的更好方法。在上面链接的 GitHub 问题中,您可以找到可能更适合您的其他方法。
这可以通过使用采用相应Func<>的方法的重载来实现。在我们的例子中,要访问组请求所需的 id 并返回具有该 id 的组,您可以尝试以下操作:
mockRequestAdapter.Setup(adapter => adapter.SendAsync(
// Needs to be correct HTTP Method of the desired method
It.Is<RequestInformation>(info => info.HttpMethod == Method.GET),
// Needs to be method from object type that will be returned from the SDK method.
Group.CreateFromDiscriminatorValue,
It.IsAny<Dictionary<string, ParsableFactory<IParsable>>>(), It.IsAny<CancellationToken>()))
.ReturnsAsync((
RequestInformation info,
// Needs to be the same type as above!
ParsableFactory<Group> _,
Dictionary<string, ParsableFactory<IParsable>> _,
CancellationToken _) =>
{
var id = (string)info.PathParameters["group%2Did"];
return new Group { Id = id };
});
Run Code Online (Sandbox Code Playgroud)
无论您现在要请求哪个组,您都将使用所需的 id 取回它:
var id = Guid.NewGuid().ToString();
var group = await graphServiceClient.Groups[id].GetAsync();
Run Code Online (Sandbox Code Playgroud)
根据您的用例和现有代码库,您还可以在构造函数调用中为两个接口提供一些空存根,并使用重写虚拟函数的功能。如果您使用文档中提供的一些模拟框架(例如 Moq),这会派上用场:
// Arrange
var mockAuthProvider = new Mock<IAuthenticationProvider>();
var mockHttpProvider = new Mock<IHttpProvider>();
var mockGraphClient = new Mock<GraphServiceClient>(mockAuthProvider.Object, mockHttpProvider.Object);
ManagedDevice md = new ManagedDevice
{
Id = "1",
DeviceCategory = new DeviceCategory()
{
Description = "Sample Description"
}
};
// setup the call
mockGraphClient
.Setup(g => g.DeviceManagement.ManagedDevices["1"]
.Request()
.GetAsync(CancellationToken.None))
.ReturnsAsync(md)
.Verifiable();
// Act
var graphClient = mockGraphClient.Object;
var device = await graphClient.DeviceManagement.ManagedDevices["1"]
.Request()
.GetAsync(CancellationToken.None);
// Assert
Assert.Equal("1",device.Id);
Run Code Online (Sandbox Code Playgroud)
通过使用这种方法,您不必费心处理在线完成的具体 HTTP 请求。相反,您可以简单地覆盖(嵌套)方法调用及其参数,并定义返回的对象,而无需序列化/反序列化步骤。另请注意,在模拟中,您可以使用例如It.IsAny<string>()和类似的构造来定义是否需要精确的参数检查或其他内容。
| 归档时间: |
|
| 查看次数: |
6853 次 |
| 最近记录: |