0

The following class has a dependency on ServiceBusClient from the Azure.Messaging.ServiceBus NuGet package (for sending Azure Service Bus messages):

public class MyService {
    private readonly ServiceBusClient _serviceBusClient;

    public MyService(ServiceBusClient serviceBusClient) {
        _serviceBusClient = serviceBusClient;
    }

    public async Task SendServiceBusMessageAsync() {
        var sender = _serviceBusClient.CreateSender("Topic_Name");
        // Send the message
    }
}

When mocking the ServiceBusClient dependency using Moq as follows, it works as desired, and the call to CreateSender returns what was specified in the setup:

    var mockServiceBusClient = new Mock<ServiceBusClient>();
    mockServiceBusClient.Setup(s => s.CreateSender(It.IsAny<string>())).Returns(new Mock<ServiceBusSender>().Object);

    var sut = new MyService(MockServiceBusClient.Object);
    await sut.SendServiceBusMessageAsync();

When attempting the same using AutoFixture.AutoMoq as shown below, the following error occurs: AutoFixture.ObjectCreationExceptionWithPath The connection string could not be parsed; either it was malformed or contains no well-known tokens.

    fixture = new Fixture();
    fixture.Customize(new AutoMoqCustomization());

    var mockServiceBusClient = fixture.Freeze<Mock<ServiceBusClient>>();
    mockServiceBusClient.Setup(s => s.CreateSender(It.IsAny<string>())).Returns(new Mock<ServiceBusSender>().Object);

    var sut = fixture.Create<MyService>();
    await sut.SendServiceBusMessageAsync();

Does anyone know how to get it to work with AutoFixture.AutoMoq?

I looked at ServiceBusClient, and I see that the parameterless constructor is protected, and the public constructor takes a connection string. I'm guessing AutoFixture.AutoMoq is using the latter, but as I understand it uses Moq. Why then does it work fine if done with Moq directly?

I think I'll just pull the method into another class and then inject and mock that, but it would be nice to understand why this is happening.

NetFx
  • 13
  • 3
  • I'm guessing AutoFixture is supplying an 'anonymous' string to the public constructor. You could register a well-formed connection string under the `string` type with AutoFixture to see if this is the problem. – David Osborne Jan 18 '23 at 08:38
  • I don't see a straightforward way of doing that, and I don't have to do that when I create the Mock myself. I found info on creating an ISpecimenBuilder implementation to do it, but I'd rather just extract the method to another class and inject and mock that instead. – NetFx Jan 18 '23 at 16:35

1 Answers1

0

You could build one with OmitAutoProperties so it will not try to pass on a connection string:

var mockServiceBusClient = fixture.Build<Mock<ServiceBusClient>>().OmitAutoProperties().Create();
fixture.Inject(mockServiceBusClient);
Fcbkevin
  • 1
  • 2
  • I just tried, and I get the same error. I think it's because it's the constructor parameter that's the issue, and not a property. I do see in the stack trace that it's using the constructor with the connection string parameter. I found this post about dealing with constructor parameters: https://stackoverflow.com/questions/26149618/autofixture-customizations-provide-constructor-parameter. It's just odd that I can mock it fine with Moq, suggesting that Moq must be using the protected parameterless constructor, so I don't know why AutoFixture.AutoMoq can't just do the same. – NetFx Jan 18 '23 at 16:12