9

I'm using a third party library class Foo that has several public methods and properties that my class uses as a dependency.

I want to test my class and mock the Foo object, but it does not have an interface. So I was thinking, I could inherit the class in a class of my own, extract an interface, and voila! I would have an injectable interface.

...but of course there are complications. Foo has a bunch of public fields. These can't go into an interface, so I'd have to write property wrappers for the fields. It's annoying.

Is there an automated way to do this? I have ReSharper, but there doesn't seem to be a way to automagically do this, which means I'm writing a lot of tedious code.

Jeremy Holovacs
  • 22,480
  • 33
  • 117
  • 254
  • Are the methods you're mocking `virtual`? If so, you can use something like Rhino Mocks' `PartialMock`. You'd be able to override/stub/mock the methods and have access to the public fields. – Adam Prescott Jul 28 '15 at 15:56
  • Hah of course not... this library was not designed to be extensible at all, and I don't think the authors ever wrote a unit test... sigh... – Jeremy Holovacs Jul 28 '15 at 15:58
  • How about this? Create a wrapper that exposes the methods as `virtual` and then use `PartialMock`! What mocking framework are you using? – Adam Prescott Jul 28 '15 at 16:01
  • Moq. Seems to do everything I want it to do. – Jeremy Holovacs Jul 28 '15 at 16:02
  • I haven't used Moq, but it looks like you can do partial mocks using the `callbase` property. http://stackoverflow.com/questions/4769928/using-moq-to-mock-only-some-methods So you can create a wrapper, expose methods as `virtual` and then use a a partial. – Adam Prescott Jul 28 '15 at 16:11
  • If you are mocking your Foo class, what is the expected behavior of the mock methods calls made by your tested class? – Rami Yampolsky Jul 28 '15 at 19:56
  • Mainly just to test that they were invoked, and returning dummy responses without kicking off a process that was out of scope for the unit test. – Jeremy Holovacs Aug 03 '15 at 21:26

2 Answers2

3

You should split your class under test into two separate classes. One class that contains the (business) logic that you need to test, and a second class that acts as an adapter to the external dependency. This adapter class should implement an interface and the logic class should depend on that interface. This interface should not mimic the API of the external dependency, but the interface should be defined in the application's needs. By doing this you achieve that you:

  • adhere to the Single Responsibility Principle, because currently your class under tests has two responsibilities.
  • adhere to the Dependency Inversion Principle by placing the new adapter behind an abstraction. This prevents your application from having to take a dependency on the external tool (only your composition root needs to depend on it), which makes your application more testable, and more maintainable.
  • adhere to the Interface Segregation Principle, that states that interfaces should be narrow and defined for the role they participate in.

What you'll end up with is an adapter class that is tightly coupled to the external library. This adapter will transform an incoming call to something that it can send on to the external library. This adapter can't be tested in isolation, and if testing is important, you'll probably need integration tests for this (depending on how the external library functions). Important to say is that you don't have to test that the external library works, but you probably still want to test the correctness of the adapter class.

Steven
  • 166,672
  • 24
  • 332
  • 435
  • What two responsibilities do you see the class having? – Jeremy Holovacs Jul 28 '15 at 16:28
  • @JeremyHolovacs: It contains both (business) logic and it is the adapter. Those are two different responsibilities. – Steven Jul 28 '15 at 16:29
  • Hmm... so you are talking about an adapter, where I was talking about a wrapper. Are these synonymous in your mind? I would think a wrapper has one responsibility: to directly translate the business logic of an external class. I wonder if we're talking about the same thing or different here? – Jeremy Holovacs Jul 28 '15 at 19:35
  • Yes, an adapter is a wrapper, but with the specific feature that it really 'adapts' from the application domain to the adapted components , instead of just mimicking the interface of the adapted component, which would simply be wrapping. – Steven Jul 28 '15 at 19:56
2

I would create a wrapper class that uses and interface you have designed that only expose what you need from Foo.

So for example:

class MyFooWrapper : IFoo
{
   private Foo _foo;
    // methods exposed by IFoo
 }

You could take further by making MyFooWrapper an abstract class to contain the properties and any other base functionality but don't put Foo in there , instead have a class that inherits the foo wrapper .

Jonathan
  • 1,725
  • 3
  • 19
  • 45