Search code examples
c#unit-testingnunitmoq

Mocking created object which then added to dictionary


How can I mock object which is created with the action in the runtime? In the following code I want to mock the Connection class for the unit test.


private readonly Dictionary<IPEndPoint, IDeviceConnection> _connections = new Dictionary<IPEndPoint, IDeviceConnection>();

private async Task DiscoveryTask(CancellationToken stoppingToken)
{
    try
    {
        while (!stoppingToken.IsCancellationRequested)
        {
                // Action which allows new Connection to be created and added to dict
                _connections.Add(
                    ipEndPoint,
                    new DeviceConnection(
                        ipEndPoint,
                        new TcpClient(),
                        stoppingToken));

                _connections[ipEndPoint].StartConnectionTask();
            }
        }
    }
    catch (Exception ex)
    {

    }
}

Advices on modification the code is acceptable.


Solution

  • Simplified: If you have something like this

    public class ExampleClass
    {
        public void DoSomething()
        {
            var someTool = new SomeTool(); // Not (easily) mockable
        }
    }
    

    you can refactor to something like this

    public interface ISomeToolFactory
    {
        SomeTool Create();
    }
    
    public class ExampleClass
    {
        private readonly ISomeToolFactory _someToolFactory;
    
        public ExampleClass(ISomeToolFactory toolFactory)
        {
             _someToolFactory = toolFactory
        }
    
        public void DoSomething()
        {
            var someTool = _someToolFactory.Create();
        }
    }
    
    // "Real" Factory =>
    public class SomeToolFactory : ISomeToolFactory
    {
        public SomeTool Create()
        {
            return new SomeTool();
        }
    }
    
    // "Test" Factory =>
    public class MockedSomeToolFactory : ISomeToolFactory
    {
        public SomeTool Create()
        {
            return Mock.Of<SomeTool>(); // whatever you need for testing
        }
    }
    
    

    Then you can inject the "Real" Factory implementation in your production code and instead use the MockedSomeToolFactory in your unit test.

    Note that this is simplified and not exactly your case. See it as a template you can modify as to your needs.