简体   繁体   中英

How do I remove dependencies to 3rd party code when unit testing?

I've got some code that performs some legacy 'database' operation and then processes the result. I want to write a unit test that checks the method that calls the legacy code without interacting with the 'database'.

My code looks something like this:

    public static bool CallRoutine(LegacySession session, /* routine params*/)
    {
        try
        {
            LegacyRoutine routine = session.CreateRoutine(/* routine params */);

            routine.Call();

            // Process result

        }
        catch (LegacyException ex)
        {
            // Perform error handling
        }
    }

Were this all my code, I would create interfaces that the LegacySession and LegacyRoutine implement and then write unit tests that use mock implementations of those interfaces using MOQ or something similar. The problem is that I don't have access to the code for LegacyRoutine or LegacySession so I can't make them implement an interface.

Any ideas about how I could do this without changing the production code too much?

If you can't access LegacyRoutine (i'm guessing it's in a referenced DLL), why not just create a wrapper for it, then flick on/off different implementations:

public interface ILegacyWrapper
{
   ILegacyRoutine CreateRoutine(); 
   // etc etc
}

public interface ILegacyRoutine
{
   // put members of LegacyRoutine
}

Know what i mean? Just mock everything out into wrappers/interfaces.

Then you could go:

ILegacyRoutine routine = session.CreateRoutine(/* routine params */)

Where session would be declared as an ILegacyWrapper , but implemented with a mock concrete.

Also, it goes without saying (but i'll say it anyway), you should consider a DI framework to make your life simpler. Otherwise you'll end with IFoo foo = new Foo() (hard-coded injection) all over the place.

StructureMap is my DI poison of choice.

HTH

You could write a thin wrapper over their API for which you did have an interface. Whether that's a practical thing to do or not rather depends on the size of the API.

Search for C# mock concrete types. Sorry, I have to run, but here's a link to the first thing I found that will solve your problem (there may be better solutions, but this looks OK):

http://docs.typemock.com/isolator/##typemock.chm/Documentation/CreatingFakesWithAAA.html

Also, check out Moq, which I've had great success with in the past

I would advise you to use a depedency injection framework. It helps you to make your classes more loosely copuled by breaking out external class dependencies into objects which are injected into your classes. These objects are often represented by an interface, which helps you to use different implementations in production and when testing. That way you won't have to actually call the external database when testing. I can recommend Ninject . It's makes dependency injection a lot easier than doing it manually.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM