简体   繁体   English

Azure Functions V2 的 MessageSender 单元测试

[英]Unit testing MessageSender for Azure Functions V2

I am trying to find the best approach for using MessageSender in my Azure function as the connection to ServiceBus, in order to unit test it.我试图找到在我的 Azure 函数中使用 MessageSender 作为到 ServiceBus 的连接的最佳方法,以便对其进行单元测试。 I have been unable to find the best way to write my code to unit test it.我一直无法找到编写代码以对其进行单元测试的最佳方法。

Code代码

public static class SomeFunction
{        
    [FunctionName("SomeFunction")]
    public static async Task Run(
          [ServiceBusTrigger("someQueue", Connection = ConnectionString)]Message message
        , [ServiceBus("someQueue", Connection = ConnectionString")]MessageSender messagesQueue
        , MessageReceiver receiver
        , string lockToken)
    {
        ...some code
    }
}          

I tried to change the MessageSender to IMessageSender but got the following binding error我试图将MessageSender更改为IMessageSender但出现以下绑定错误

Binding Error绑定错误

System.InvalidOperationException: "Can't bind ServiceBus to type 'Microsoft.Azure.ServiceBus.Core.IMessageSender."

Then switched it back to the MessageSender and tried mocking it and once I ran my test I got the error below.然后将其切换回MessageSender并尝试模拟它,一旦我运行测试,我就会收到以下错误。

Unit Test Example单元测试示例

[TestMethod]
public async Task Run_ValidMessage_Expect_Run_Succesfully()
{
    var sbBuilder = new ServiceBusConnectionStringBuilder(ActualSbConnectionString);
    Mock<MessageSender>sender = new Mock<MessageSender>(sbBuilder, RetryPolicy.Default);
    SomeFunction.Run(_sender.Object);
}
Error: 
threw exception: 
    System.ArgumentException: The argument  is null or white space.
  Stack Trace: 
    at MessageSender.ctor(String entityPath, String transferDestinationPath, Nullable`1 entityType, ServiceBusConnection serviceBusConnection, ICbsTokenProvider cbsTokenProvider, RetryPolicy retryPolicy)
    at MessageSender.ctor(String connectionString, String entityPath, RetryPolicy retryPolicy)

I have been unable to write the code with a working unit test and function.我一直无法使用工作单元测试和函数编写代码。 any pointers would be helpful.任何指针都会有所帮助。

Edit: included omitted args编辑:包括省略的参数

From your code, there are few errors, firstly it should be ServiceBusTrigger binding not the ServiceBus cause you don't show your trigger bingding or you omit it.从您的代码来看,几乎没有错误,首先它应该是ServiceBusTrigger绑定而不是ServiceBus因为您没有显示触发器绑定或省略它。 Then if your trigger is ServiceBusTrigger , you could only bind MessageReceiver , MessageSender is for ServiceBus .然后,如果您的触发器是ServiceBusTrigger ,则只能绑定MessageReceiverMessageSender用于ServiceBus Sample code . 示例代码

And the below is my test code, ServiceBusTrigger to receive the message, ServiceBus to send the message.下面是我的测试代码,ServiceBusTrigger 接收消息,ServiceBus 发送消息。 I use the Microsoft.Azure.WebJobs.Extensions.ServiceBus 3.0.3 .我使用Microsoft.Azure.WebJobs.Extensions.ServiceBus 3.0.3

[FunctionName("Function1")]
    public static async System.Threading.Tasks.Task RunAsync([ServiceBusTrigger("myqueue", Connection = "ConnectionString")]
        MessageReceiver messageReceiver,
        ILogger log, 
        [ServiceBus("test", Connection = "ConnectionString")]MessageSender messagesQueue)
    {
        Console.Write(messageReceiver.Path);

        Message m1 = await messageReceiver.PeekAsync();

        await messagesQueue.SendAsync(m1);

    }

This works for me, you could have a try if this code is what you want.这对我有用,如果此代码是您想要的,您可以尝试一下。 If you still have problem, please feel free to let me know.如果您仍有问题,请随时告诉我。

A bit late to the party, but I hit this issue and found a work around.聚会有点晚了,但我遇到了这个问题并找到了解决方法。

Instead of having the MessageSender as a parameter in the Run method, I ctor inject a Func<MessageSender> into the function class.不是将MessageSender作为Run方法中的参数,而是将Func<MessageSender>注入到函数类中。

Note: I acknowledge it would probably be better if I could unit test without needing to go down this approach, but I couldn't get it working any other way...注意:我承认如果我可以在不需要采用这种方法的情况下进行单元测试可能会更好,但是我无法以任何其他方式让它工作......

eg例如

   public class SomeFunction
   {
      private readonly Func<IMessageSender> _messageSenderFactory;

      public SomeFunction(
         Func<IMessageSender> messageSenderFactory)
      {
         _messageSenderFactory = messageSenderFactory;
      }

      [FunctionName("SomeFunction")]
      public static async Task Run(
         [ServiceBusTrigger("someQueue", Connection = ConnectionString)]Message message,
         MessageReceiver receiver, 
         string lockToken)
      {
         // ...
         var messageSender = _messageSenderFactory.Invoke();
         await messageSender.SendAsync(message);
      }
   }

Have to register Func<IMessageSender> for DI in startup.cs:必须在 startup.cs 中为 DI 注册Func<IMessageSender>

         services.AddSingleton<Func<IMessageSender>>(() =>
            new MessageSender(Environment.GetEnvironmentVariable("SERVICE_BUS_CONNECTION"),
               Environment.GetEnvironmentVariable("someQueue")));

Can then mock the Func<IMessageSender> in unit tests.然后可以在单元测试中模拟Func<IMessageSender>

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

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