简体   繁体   English

如何在 xUnit 中模拟委托

[英]How to mock Delegate in xUnit

I have delegate that call SendMessagesAsync method which takes IEnumerable ProviderExemptionReceivedNotification.我有委托调用SendMessagesAsync方法,该方法采用 IEnumerable ProviderExemptionReceivedNotification。 How I mock SendMessagesAsync that is callBack of delegate.我如何模拟作为委托回调的 SendMessagesAsync。 In other word how I moq Delegate?换句话说,我如何起订量委托?

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();
    }

You can't mock a delegate.你不能嘲笑一个代表。 You cant mock that expression either since it is hard-coded into the subject under test.您也不能模拟该表达式,因为它被硬编码到被测对象中。

You need to capture the delegate in a Moq Callback and invoke it there.您需要在 Moq Callback中捕获委托并在那里调用它。 That is the only option available given the shown subject under test.鉴于显示的测试对象,这是唯一可用的选项。

Here is an oversimplified minimum reproducable example of a subject under test based on your previous posts.这是基于您之前的帖子的被测主题的过度简化的最小可重现示例。

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);
    }
}

The test for the subject provided above, which includes the Callback capturing the delegate (handler) and invoking it, actually runs as expected when exercsed.上面提供的主题测试,包括捕获委托(处理程序)并调用它的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();
    }
}

You will need to adapt this example to what you are trying to do.您将需要调整此示例以适应您正在尝试做的事情。 It won't copy exactly as written here.它不会完全按照这里写的那样复制。

You may still run into problem since you have not shown what SendMessagesAsync is doing to ensure that a safe path can be mocked through its invocation.您可能仍然会遇到问题,因为您没有展示SendMessagesAsync正在做什么以确保可以通过其调用来模拟安全路径。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM