Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSubstitute mock generic method

I have the following method signature in an interface:

public interface ISettingsUtil
{
    T GetConfig<T>(string setting, dynamic settings);
}

Which I have attempted to mock:

var settingsUtil = Substitute.For<ISettingsUtil>();
var maxImageSize = settingsUtil.GetConfig<long>("maxImageSize", 
                                              Arg.Any<dynamic>()).Returns(100L);

This throws a Microsoft.CSharp.RuntimeBinder.RuntimeBinderException exception on the 2nd line:

'long' does not contain a definition for 'Returns'

Any thoughts on how to mock T GetConfig<T>(string setting, dynamic settings) correctly?

like image 970
Anders Avatar asked Feb 18 '23 15:02

Anders


1 Answers

For anyone still struggling with this, you can actually mock dynamics in NSubsitute, it just requires jumping through some minor hoops. See the below case of mocking out calls to a signalR client hub.

The important line is this one:

SubstituteExtensions.Returns(_hubContext.Clients.All, _mockClient);

In order to mock the dynamic I have created an interface with the methods I want to listen for. You then need to use SubstituteExtensions.Returns rather than simply chaining a .Returns at the end of the object.
If you don't need to verify anything you could also use an anonymous object.

Full code sample follows:

[TestFixture]
public class FooHubFixture
{
    private IConnectionManager _connectionManager;
    private IHubContext _hubContext;
    private IMockClient _mockClient;

    [SetUp]
    public void SetUp()
    {
        _hubContext = Substitute.For<IHubContext>();
        _connectionManager = Substitute.For<IConnectionManager>();

        _connectionManager.GetHubContext<FooHub>().Returns(_hubContext);
        _mockClient = Substitute.For<IMockClient>();
        SubstituteExtensions.Returns(_hubContext.Clients.All, _mockClient);
    }

    [Test]
    public void PushFooUpdateToHub_CallsUpdateFooOnHubClients()
    {
        var fooDto = new FooDto();
        var hub = new FooHub(_connectionManager);
        hub.PushFooUpdateToHub(fooDto);
        _mockClient.Received().updateFoo(fooDto);
    }

    public interface IMockClient
    {
        void updateFoo(object val);
    }
}



public class FooHub : Hub
    {
        private readonly IConnectionManager _connectionManager;

        public FooHub(IConnectionManager connectionManager)
        {
            _connectionManager = connectionManager;
        }

        public void PushFooUpdateToHub(FooDto fooDto)
        {
            var context = _connectionManager.GetHubContext<FooHub>();
            context.Clients.All.updateFoo(fooDto);
        }
    }
like image 115
Brett Christensen Avatar answered Feb 21 '23 03:02

Brett Christensen