1

I am using some COM library in my C# which is bound to particular hardware and doesn't work without it. On development/testing computer I don't have that hardware. The method which is using library looks like this:

using HWSysManagerLib;
bool ProcessBias(HWSysManager systemManager, string hwPath)
{
    int handle = systemManager.OpenConfiguration(hwPath);
    ...
    // some magic goes here
    // return result
}

The question is, can I mock HWSysManager for test method and how? There are few methods only in HWSysManager and it wouldn't be problem to simulate their functionality for test. A tiny example would be great on how to mock it, if it's possible at all.

Pablo
  • 28,133
  • 34
  • 125
  • 215

3 Answers3

5

You can use the adapter pattern here.

Create an interface named IHWSysManager

public interface IHWSysManager
{
    int OpenConfiguration(string hwPath);
}

The real implementation class just delegates the work to the library:

public class HWSysManagerImpl : IHWSysManager
{
    private HWSysManager _hwSysManager; //Initialize from constructor

    public int OpenConfiguration(string hwPath)
    {
        return _hwSysManager.openConfiguration(hwPath);
    }
}

Use the interface in your code like this:

bool ProcessBias(IHWSysManager systemManager, string hwPath)
{
    int handle = systemManager.OpenConfiguration(hwPath);
    ...
    // some magic goes here
    // return result
}

Now you can mock your IHWSysManager interface with mock frameworks or you can create a stub class yourself.

Yusuf Tarık Günaydın
  • 3,016
  • 2
  • 27
  • 41
  • So it's inevitable to alter my app. Even though, how I call `ProcessBias` from within my app? Right now I call it like this: `HWSysManager sm = new HWSysManager(); ProcessBias(sm, "");` – Pablo Oct 03 '15 at 12:32
  • Basically I have to implement all method delegates, which I used from that library. – Pablo Oct 03 '15 at 12:37
  • You should not create an instance in the calling method. Instead take the IHWSysManager from constructor. In your development machine give the stub class as parameter, and in actual environment give the real implementation class. This technique is called Dependency Injection, you can read about it [here](http://stackoverflow.com/questions/130794/what-is-dependency-injection). – Yusuf Tarık Günaydın Oct 03 '15 at 12:59
1

You can use Typemock Isolator for faking HWSysManager.

For your example, you can do the following:

var fakeManager = Isolate.Fake.Instance<HWSysManager>();

Isolate.WhenCalled(() => fakeManager.OpenConfiguration("")).WillReturn(0);

And then, you can pass this faked manager to ProcessBias(IHWSysManager systemManager, string hwPath) as an argument.

As you said, you can simulate a few methods from IHWSysManager. So, me advice is to set up the behavior of this manager's methods using DoInstead():

Isolate.WhenCalled(() => fakeManager.OpenConfiguration("")).DoInstead(
    context =>
    {
        //Your simulation
    });

You can look here for more information. I think, it can be really useful for you.

JamesR
  • 745
  • 4
  • 15
-1

I suppose you should create HWSysManager(or some other name) class to your Mock cases, add there some wanted methods and then mock them. For example:

    class HWSysManager
    {
        public virtual int ExampleReturnIntMethod(int a)
        {
            var someInt = 0;
            return someInt;
        }

and then setup:

    public void TestMethod()
    {
        Mock<HWSysManager> hwSysManager = new Mock<HWSysManager>();
        hwSysManager.Setup(x => x.ExampleReturnInMethod(It.IsAny<int> ())).Returns(10); //if parameter is any of int, return 10 in this case
    }

Then to use your Mocked object just use the 'object' property:

 var hwSysInstance = hwSysManager.Object;
 var result = hwSysInstance.ExampleReturnInMethod(2); //result will be 10 in this case - as we have mocked

In case above your methods/properties have to be virtual.

You can use interfaces also, in your case:

    public interface HwsysManager
    {
        int OpenConfiguration(string hwPath);
    }

     public void TestMethod()
    {
      Mock<HwsysManager> hwsysManager = new Mock<HwsysManager>();

      hwsysManager.Setup(x => x.OpenConfiguration(It.IsAny<string>())).Returns(10);
    }

All features of this Mock library are described here: https://github.com/Moq/moq4/wiki/Quickstart

M G
  • 154
  • 1
  • 4
  • Actually I need to test method, which is using `HWSysManager`. So if I follow your suggestion, I got a type error: cannot convert from `Moq.Mock` to `HWSysManagerLib.HWSysManager`. In TestMethod I have `bool b = ClientProgram.ProcessBias(tcsm)`. `tcsm is mock object. So I suspect it is not possible to cheat here? – Pablo Oct 03 '15 at 10:37
  • so tcsm actually is tcsm.Object, but still the same error. – Pablo Oct 03 '15 at 10:56
  • Moreover, I have got an error in TestClass that the assembly which is defining `HWSysManagerLib.HWSysManager` is not referenced. – Pablo Oct 03 '15 at 11:04