Search Results for

    Show / Hide Table of Contents

    Testing your code with .NET Adapter

    With the new version of the .NET Adapter, it is now much possible to write unit tests that mock various aspects of the adapter.

    The changes that have taken place to enable this include:

    • Builder-style runtime creation
    • A mockable type resolution service
    • The returning of interfaces from creation methods rather than concrete types

    An Example

    This example assume you have a simple model class that reacts to interop context changes by setting a property with a field from the context payload.

    Ideally you would want to unit test this in isolation of OpenFin by passing in a variety of scenarios to the context receiver and asserting that the model handles these as expected.

    The code to be tested

    For the purposes of this example, the model class looks like the following.

    internal class MainWindowVM
    {
        private readonly IRuntime runtime;
        private IChannelClient channelClient;
    
        public string CurrentId { private set; get; }
    
        // Now we pass in the runtime interface when we create the model
        public MainWindowVM(IRuntime runtime)
        {
            this.runtime = runtime;
    
            // Connect to the broker and add a handler for a context change
            var interop = runtime.GetService<IInterop>();
            interopClient = await interop.ConnectAsync("the-broker");        
    
            await interopClient.AddContextHandlerAsync(HandleContext, "my-context");
        }
    
        private void HandleContext(Context context)
        {
            if (context.Type == "fdc3.contact")
            {
                if ((context.Id as JsonObject).TryGetPropertyValue("email", out var valueNode))
                {
                    CurrentId = valueNode.ToString();
                }
            }
        }    
    }
    

    The Tests

    Now we will create a simple test that checks that the CurrentId property within the model is updated only on an fdc3 contact context change.

    Note

    For mocking we make use of the popular MOQ library. You may use any mocking library that you prefer such as Rhino Mocks.

    [TestClass]
    public class InteropTests
    {
        [TestMethod]
        public void TestCurrentIdIsCorrectlySetAfterAContextChange()
        {
            // First we need to setup our mocks...
    
            ContextHandler contextHandler = null;
    
            // Create a Mock for IRuntime
            var runtimeMock = new Mock<IRuntime>();
    
            // Create a mock for the entire IInterop api
            var interopMock = new Mock<IInterop>();
    
            // Setup the IRuntime so that when the model asks for IInterop we return our own mock
            runtimeMock.Setup(x => x.GetService<IInterop>())
                       .Returns(interopMock.Object);
    
            // Create a mock for the entire IInteropClient api
            var interopClientMock = new Mock<IInteropClient>();
            
            // Now create a setup on the IInterop mock for when the model connects to the broker 
            // We return our previously create IInteropClient Mock
            interopMock.Setup(x => x.ConnectAsync("the-broker"))
                       .ReturnsAsync( interopClientMock.Object );
    
            // When the model adds a handler for a context change, we want out test to intercept that and store
            // the handler so we can invoke it directly later
            interopClientMock.Setup(x => x.AddContextHandlerAsync(It.IsAny<ContextHandler>(), "my-context"))
                             .Callback((ContextHandler handler, string contextType) =>
                             {
                                 contextHandler = handler;
                             });
    
            // Now we can test the model...
    
            // Create our model and give it the runtime mock
            // This will in turn connect to the broker and invoke the various setups above
            var vm = new MainWindowVM(runtimeMock.Object);
    
            // Should have the context handler now ready for us to invoke directly with a dummy context
            Assert.IsNotNull(contextHandler, "AddContextHandler should have been called by this point");
    
            // Set an initial context
            contextHandler(new Context
            {
                Type = "fdc3.contact",
                Id = new JsonObject
                        {
                            { "email", "john.mchugh@gmail.com" }
                        }
            });
    
            Assert.AreEqual("john.mchugh@gmail.com", vm.CurrentId);
    
            // Change it
            contextHandler(new Context
            {
                Type = "fdc3.contact",
                Id = new JsonObject
                        {
                            { "email", "mary.rose@hotmail.com" }
                        }
            });
    
            // Should have changed
            Assert.AreEqual("mary.rose@hotmail.com", vm.CurrentId);
    
            // Fire a context that is a different context type
            contextHandler(new Context
            {
                Type = "fdc3.instrument",
                Id = new JsonObject
                        {
                            { "isin", "abcdefg123" }
                        }
            });
    
            // Should have ignored this update
            Assert.AreEqual("mary.rose@hotmail.com", vm.CurrentId);
        }
    }
    

    Conclusion

    Using the above example, you should now be able to invoke your own code using mock .NET adapter objects without any need to write your own wrapper around the adapter or running an actual OpenFin runtime during tests.

    In This Article
    Back to top Copyright OpenFin