views:

97

answers:

2

I have an application in VB/C# .NET which needs to interact with a third party API, but I would like to interface it out so I can use a mock API for testing purposes. Here are example API calls I would use in code:

RelayClient.AuthenticateUser(username, password, request, sessionID)
RelayClient.GetUserInfo(sessionID)

A few problems I am facing:

  1. RelayClient is NonInheritable/Static.
  2. RelayClient doesn't implement any interfaces.
  3. The API client library is closed source.

Is there any standard way of dealing with this situation?

+1  A: 

If you don't want to roll your own abstraction, have a look at TypeMock Isolator- it uses profiler hooks to do runtime class-level mocking of pretty much anything, whether you own it or not. It actually does a runtime substitution of the type implementation and intercepts all the calls (eg, you don't need to subclass the type- as far as the CLR is concerned, you ARE the type).

It's commercial, but they do have a free trial. Depending on how big the thing you need to mock is, the $799 can be well worth the time abstracting/wrapping the entire API surface if it's not interface-based.

nitzmahone
+1  A: 

The way to do this would be to make your code work against 'middle-man' non-static classes, which internally use the static classes from your 3rd party API. You then mock out these 'middle-man' classes for your unit tests.

Something like... (untested code)

// your consuming class
public class MyClass
{
    private readonly RelayClientManager manager;

    public MyClass(RelayClientManager manager)
    {
        this.manager = manager;
    }

    public UserInfo GetUserInfo(int sessionID)
    {
        return manager.GetUserInfo(sessionID);
    }    
}

// 'middle-man' class
public class RelayClientManager
{
    public UserInfo GetUserInfo(int sessionID)
    {
        return RelayClient.GetUserInfo(sessionID);
    }
}

// unit test (using xUnit.net and Moq)
[Fact]
public static void GetsUserInfo()
{
    // arrange
    var expected = new UserInfo();
    var manager = new Mock<RelayClientManager>();
    manager.Setup(x => x.GetUserInfo(0)).Returns(expected);
    var target = new MyClass(manager);        

    // act
    var actual = target.GetUserInfo(0);

    // assert
    Assert.Equal(expected, actual);
}
AdamRalph
This is very similar to the solution I implemented, except I manually create the mock classes and populate with fixed data. I will check out xUnit.net and Moq and see how those work.
Kevin
just to clarify - xUnit.net is a unit testing framework and Moq is a mocking framework. these two are my respective favourites but the approach I've described will work just as well with many other alternatives, e.g. NUnit and RhinoMocks
AdamRalph