简体   繁体   English

NSubstitute模拟通用方法

[英]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: 这会在第二行引发Microsoft.CSharp.RuntimeBinder.RuntimeBinderException异常:

'long' does not contain a definition for 'Returns' 'long'不包含'Returns'的定义

Any thoughts on how to mock T GetConfig<T>(string setting, dynamic settings) correctly? 有关如何正确模拟T GetConfig<T>(string setting, dynamic settings)任何想法?

For anyone still struggling with this, you can actually mock dynamics in NSubsitute, it just requires jumping through some minor hoops. 对于仍在努力解决这个问题的人来说,你实际上可以在NSubsitute中模拟动态,它只需要跳过一些小箍。 See the below case of mocking out calls to a signalR client hub. 请参阅以下模拟调用signalR客户端集线器的情况。

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. 然后,您需要使用SubstituteExtensions.Returns,而不是简单地在对象的末尾链接.Returns。
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);
        }
    }

NSubstitute does not work with members that use dynamic . NSubstitute不适用于使用dynamic成员。 ( Github issue ) Github问题

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

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