如何在 xUnit 中模拟委托
How to mock Delegate in xUnit
我有调用 SendMessagesAsync
方法的委托,该方法采用 IEnumerable ProviderExemptionReceivedNotification。我如何模拟作为委托回调的 SendMessagesAsync。换句话说,我如何最小起订量委托?
Interface
public delegate Task<bool> SendAnprProviderExemptionNotifications(IEnumerable<ProviderExemptionReceivedNotification> exemptions);
public interface IRingGoApiService
{
Task<RingGoMessageResponseResult> ProcessCreateRequestAsync(RingGoExemption ringGoExemption, SendAnprProviderExemptionNotifications sendProviderExemption);
}
Delegate Implementation
public async Task<RingGoMessageResponseResult> ProcessCreateRequestAsync(RingGoExemption ringGoExemption, SendAnprProviderExemptionNotifications sendProviderExemption)
{
var msgSent = await sendProviderExemption(new List<ProviderExemptionReceivedNotification>() { exemption });
}
Test Class
public MyTestClass{
public MyTestClass()
{
}
private readonly Mock<IProviderExemptionService> providerExemptionServiceMoq;
}
using delegate
var result = await _ringGoApiService.ProcessCreateRequestAsync(ringGoExemption,
async (IEnumerable<ProviderExemptionReceivedNotification> exemptions) => await SendMessagesAsync(servicebusMessage, exemptions)
);
SendMessagesAsync
static async Task<bool> SendMessagesAsync(IAsyncCollector<Message> collector, IEnumerable<ProviderExemptionReceivedNotification> exemptions)
{
SetProviderExemption(exemptions);
var messages = exemptions.Select(exemption =>
{
//Creating ServiceBus Message...
return message;
});
}
static void SetProviderExemption(IEnumerable<ProviderExemptionReceivedNotification> exemptions)
{
providerExemption = exemptions.FirstOrDefault();
}
你不能嘲笑代表。你也不能嘲笑那个表达式,因为它被硬编码到被测对象中。
您需要在 Moq Callback
中捕获委托并在那里调用它。这是给定显示的测试对象的唯一可用选项。
这是一个基于您之前的帖子的被测主题的过度简化的最小可重现示例。
public delegate Task<bool> SendAnprProviderExemptionNotifications(IEnumerable<ProviderExemptionReceivedNotification> exemptions);
public interface IRingGoApiService {
Task<RingGoMessageResponseResult> ProcessCreateRequestAsync(RingGoExemption ringGoExemption, SendAnprProviderExemptionNotifications sendProviderExemption);
}
public class RingGoMessageResponseResult { }
public class ProviderExemptionReceivedNotification { }
public class RingGoExemption : Exception { }
public interface IActionResult { }
public class OverSimplifiedExample {
private readonly IRingGoApiService ringGoApiService;
public OverSimplifiedExample(IRingGoApiService ringGoApiService) {
this.ringGoApiService = ringGoApiService;
}
public async Task<bool> Run() {
RingGoExemption ringGoExemption = new RingGoExemption();
RingGoMessageResponseResult result = await ringGoApiService.ProcessCreateRequestAsync(ringGoExemption, myDelegate);
return result != null;
}
private Task<bool> myDelegate(IEnumerable<ProviderExemptionReceivedNotification> exemptions) {
return Task.FromResult(true);
}
}
上面提供的主题测试,其中包括 Callback
捕获委托(处理程序)并调用它,实际上 运行 在执行时符合预期。
[TestFixture]
public class MyTestClass {
[Test]
public async Task MyTestMethod() {
//Arrange
Mock<IRingGoApiService> mock = new Mock<IRingGoApiService>();
RingGoMessageResponseResult ringGoMessageResponseResult = new RingGoMessageResponseResult();
mock
.Setup(_ => _.ProcessCreateRequestAsync(It.IsAny<RingGoExemption>(), It.IsAny<SendAnprProviderExemptionNotifications>()))
.ReturnsAsync(ringGoMessageResponseResult)
.Callback((RingGoExemption exception, SendAnprProviderExemptionNotifications handler) => {
var whateverMyExemptionsAre = Enumerable.Empty<ProviderExemptionReceivedNotification>();
handler.Invoke(whateverMyExemptionsAre);
});
var subject = new OverSimplifiedExample(mock.Object);
//Act
var actual = await subject.Run();
//Assert
actual.Should().BeTrue();
}
}
您需要根据您的尝试调整此示例。它不会完全按照这里写的那样复制。
您可能仍然 运行 遇到问题,因为您没有显示 SendMessagesAsync
正在做什么以确保可以通过其调用模拟安全路径。
我有调用 SendMessagesAsync
方法的委托,该方法采用 IEnumerable ProviderExemptionReceivedNotification。我如何模拟作为委托回调的 SendMessagesAsync。换句话说,我如何最小起订量委托?
Interface
public delegate Task<bool> SendAnprProviderExemptionNotifications(IEnumerable<ProviderExemptionReceivedNotification> exemptions);
public interface IRingGoApiService
{
Task<RingGoMessageResponseResult> ProcessCreateRequestAsync(RingGoExemption ringGoExemption, SendAnprProviderExemptionNotifications sendProviderExemption);
}
Delegate Implementation
public async Task<RingGoMessageResponseResult> ProcessCreateRequestAsync(RingGoExemption ringGoExemption, SendAnprProviderExemptionNotifications sendProviderExemption)
{
var msgSent = await sendProviderExemption(new List<ProviderExemptionReceivedNotification>() { exemption });
}
Test Class
public MyTestClass{
public MyTestClass()
{
}
private readonly Mock<IProviderExemptionService> providerExemptionServiceMoq;
}
using delegate
var result = await _ringGoApiService.ProcessCreateRequestAsync(ringGoExemption,
async (IEnumerable<ProviderExemptionReceivedNotification> exemptions) => await SendMessagesAsync(servicebusMessage, exemptions)
);
SendMessagesAsync
static async Task<bool> SendMessagesAsync(IAsyncCollector<Message> collector, IEnumerable<ProviderExemptionReceivedNotification> exemptions)
{
SetProviderExemption(exemptions);
var messages = exemptions.Select(exemption =>
{
//Creating ServiceBus Message...
return message;
});
}
static void SetProviderExemption(IEnumerable<ProviderExemptionReceivedNotification> exemptions)
{
providerExemption = exemptions.FirstOrDefault();
}
你不能嘲笑代表。你也不能嘲笑那个表达式,因为它被硬编码到被测对象中。
您需要在 Moq Callback
中捕获委托并在那里调用它。这是给定显示的测试对象的唯一可用选项。
这是一个基于您之前的帖子的被测主题的过度简化的最小可重现示例。
public delegate Task<bool> SendAnprProviderExemptionNotifications(IEnumerable<ProviderExemptionReceivedNotification> exemptions);
public interface IRingGoApiService {
Task<RingGoMessageResponseResult> ProcessCreateRequestAsync(RingGoExemption ringGoExemption, SendAnprProviderExemptionNotifications sendProviderExemption);
}
public class RingGoMessageResponseResult { }
public class ProviderExemptionReceivedNotification { }
public class RingGoExemption : Exception { }
public interface IActionResult { }
public class OverSimplifiedExample {
private readonly IRingGoApiService ringGoApiService;
public OverSimplifiedExample(IRingGoApiService ringGoApiService) {
this.ringGoApiService = ringGoApiService;
}
public async Task<bool> Run() {
RingGoExemption ringGoExemption = new RingGoExemption();
RingGoMessageResponseResult result = await ringGoApiService.ProcessCreateRequestAsync(ringGoExemption, myDelegate);
return result != null;
}
private Task<bool> myDelegate(IEnumerable<ProviderExemptionReceivedNotification> exemptions) {
return Task.FromResult(true);
}
}
上面提供的主题测试,其中包括 Callback
捕获委托(处理程序)并调用它,实际上 运行 在执行时符合预期。
[TestFixture]
public class MyTestClass {
[Test]
public async Task MyTestMethod() {
//Arrange
Mock<IRingGoApiService> mock = new Mock<IRingGoApiService>();
RingGoMessageResponseResult ringGoMessageResponseResult = new RingGoMessageResponseResult();
mock
.Setup(_ => _.ProcessCreateRequestAsync(It.IsAny<RingGoExemption>(), It.IsAny<SendAnprProviderExemptionNotifications>()))
.ReturnsAsync(ringGoMessageResponseResult)
.Callback((RingGoExemption exception, SendAnprProviderExemptionNotifications handler) => {
var whateverMyExemptionsAre = Enumerable.Empty<ProviderExemptionReceivedNotification>();
handler.Invoke(whateverMyExemptionsAre);
});
var subject = new OverSimplifiedExample(mock.Object);
//Act
var actual = await subject.Run();
//Assert
actual.Should().BeTrue();
}
}
您需要根据您的尝试调整此示例。它不会完全按照这里写的那样复制。
您可能仍然 运行 遇到问题,因为您没有显示 SendMessagesAsync
正在做什么以确保可以通过其调用模拟安全路径。