0

I am developing an .NET core OPC client on VS2019 using a commercial library to communicate with an OPC server. I am trying to test my code with Nunit and FakeItEasy. I need to Fake calls to a class Discovery but the members are non-virtual and FakeItEasy is unable to fake them. This is code that calls a Discovery method.

    public List<ApplicationDescription> FindServers(ApplicationInstanceBase applicationInstance, string serverName, string serverPort)
{
    try
    {
        // Discovery URL 
        _discoveryUrl = "opc.tcp://" + serverName + ":" + serverPort;

        Discovery discovery = new Discovery(applicationInstance);
        return discovery.FindServers(_discoveryUrl);
    }
    catch (Exception)
    {
    }
}

And this is the test code

    [Test]
public void FindServersTest__simple()
{
    _serverList = CreateServerList(); //create 2 dummy servers
    
    Discovery _discovery = A.Fake<Discovery>(x => x.WithArgumentsForConstructor(() => new Discovery(A<ApplicationInstanceBase>.Ignored)));
    A.CallTo(() => _discovery.FindServers(A<string>.Ignored)).Returns(_serverList);

    List<ApplicationDescription> servers = _opcClient.FindServers(_applicationInstance, _OPCServer, _OPCServerPort);
    Assert.AreEqual(servers.Count, 2);
}

I get the following error message

Message: FakeItEasy.Configuration.FakeConfigurationException :

 The current proxy generator can not intercept the method UnifiedAutomation.UaClient.Discovery.FindServers(System.String discoveryUrl) for the following reason:
   - Non-virtual members can not be intercepted. Only interface members and virtual, overriding, and abstract members can be intercepted.

Because this is a commercial library I cannot make any changes to their code. Any ideas how I can get round this?

sdmorris
  • 339
  • 1
  • 7
  • 18
  • 6
    Build your own interface. Implement the interface in a new class. Have that new class call the commercial library. Have your original code call your interface rather than the commercial library. Mock the interface to your heart's content. – mjwills Jul 16 '21 at 09:39
  • 1
    @mjwills, this is totally the answer. Make it an answer and _I'll_ vote for it, at least… – Blair Conrad Jul 16 '21 at 10:25
  • I already tried that and it did not appear to work. It is good to know that that is the correct answer and I was going in the right direction. I will go back and check my implementation. – sdmorris Jul 16 '21 at 14:08
  • Oh, late-breaking news: in your test code, the Fake `_discovery` _is never provided to the system under test_, which may explain your "new" failure. If your code-to-be-tested doesn't have the Fake, it can't use it. I talk a bit more about this in [another answer](https://stackoverflow.com/a/67729088/1199), if you're interested. – Blair Conrad Jul 16 '21 at 19:14

0 Answers0