erik
erik

Reputation: 1278

How test code with lots of dependencies

I am working on a large codebase with basically no unit test coverage. We are about to start moving toward a more test-driven approach, so I thought I would try to write a unit test for a very simple function I added, basically

class ClassUnderTest  {
    public void SetNoMatchingImage() {
        currentState.State = FSMState.NoMatchingImage;
        ... // Some more logic
        NotifyViews();
    }

    public ViewStatus GetStatus() {
        ...
        if (currentState.State == FSMState.NoMatchingImage)
           return ViewStatus.EmptyScreen;
        ...
    }

    ...
}

Ok, so test this, I would just like to do:

[Test]
public void TestSetNoMatchingImage() {
    ClassUnderTest view = new ClassUnderTest(...);
    view.SetNoMatchingImage();  
    Assert.AreEqual(ViewStatus.EmptyScreen, view.Status); 
}

But my problem here is that the ClassUnderTest constructor takes 3 arguments to non-interfaces that cannot be null, so I cannot easily create a ClassUnderTest. I can try to either create instances of these classes or stub them, but the problem is the same for them: each of the contructors take arguments that has to be created. And the problem is the same for... and so on. The result is of course a very large overhead and a lot of code needed even for very simple tests.

Is there a good way of dealing with cases like this to make the test cases easier to write?

Upvotes: 2

Views: 319

Answers (3)

ipr101
ipr101

Reputation: 24236

I'd second the recommendation for Typemock, and the solutions suggested in the other answers. In addition to what's already being said Michael Feathers has written a book dealing with the patterns that you're bumping up against called 'Working Effectively With Legacy Code' -

http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052/ref=sr_1_1?ie=UTF8&qid=1313835584&sr=8-1

There's a PDF extract here - http://www.objectmentor.com/resources/articles/WorkingEffectivelyWithLegacyCode.pdf

Upvotes: 0

Augusto
Augusto

Reputation: 29867

You'll have lots of situations like this when you start refactoring a project without tests if it wasn't design with Dependency Injection in mind and the mocking framework you use cannot mock concrete classes (such as NMock).

As Andriys just mentioned, Typemock (and moq too) can mock concrete classes as long as it got virtual members.

Personally, I would extract an interface from each of those three classes and inject the interfaces as part of some refactoring to make the class easy to test. I can't remember if VS has a refactor to extract an interface in 2 clicks, which wouldn't take too long.

Upvotes: 2

andriys
andriys

Reputation: 2222

I would recommend looking at Typemock Isolator framework. According to Art of Unit Testing book by Roy Osherove, it's your best bet when writing unit tests for legacy code:

...it’s the only one [framework] that allows you to create stubs and mocks of dependencies in production code without needing to refactor it at all, saving valuable time in bringing a component under test.

Cheers!

Upvotes: 1

Related Questions