19

How can I write a unit test for a method that has a using statement?

For example let assume that I have a method Foo.

public bool Foo()
{
    using (IMyDisposableClass client = new MyDisposableClass())
    {
        return client.SomeOtherMethod();
    }
}

How can I test something like the code above?

Sometimes I choose not to use using statement and Dispose() an object manually. I hope that someone will show me a trick I can use.

Jay Bazuzi
  • 45,157
  • 15
  • 111
  • 168
Vadim
  • 21,044
  • 18
  • 65
  • 101
  • What is TDD? The only expansion I know of is Test-Driven Development. – Michael Myers Dec 23 '09 at 16:09
  • It is Test Driven Development. – Vadim Dec 23 '09 at 16:10
  • So your question is "How can I test-driven development something like the code above?" – Michael Myers Dec 23 '09 at 16:11
  • 3
    Test-driven develop. Cut some slack with the conjugation :) – Matthew Groves Dec 23 '09 at 16:25
  • 2
    Well, I was also trying to point out that you can't "test-driven develop" code that already exists. But that's been mentioned in several answers now. – Michael Myers Dec 23 '09 at 16:33
  • The title is "How to TDD method with `using` statement?" but then you say "Sometimes I choose not to use `using` statement and `Dispose` an object manually." That only serves to confuse. Also, this doesn't look like TDD to me; you don't have a test but you have a method that you want to test. In TDD tests come first; there are no methods without tests. So it seems this is more about how to unit test that `Dispose` is called. So how about "How to unit test that `Dispose` is called?" Then the unambiguous answer is pass in the dependency `IMyDisposableClass` and mock. `new` is evil in testing. – jason Dec 23 '09 at 17:52

8 Answers8

23

If you construct the IMyDisposableClass using a factory (injected into the parent class) rather than using the new keyword, you can mock the IMyDisposable and do a verify on the dispose method call.

public bool Foo()
{
    using (IMyDisposableClass client = _myDisposableClassFactory.Create())
    {
        return client.SomeOtherMethod();
    }
}
mcintyre321
  • 12,996
  • 8
  • 66
  • 103
  • Alternately, you can use a virtual factory method, and test a specialization of that object that returns an appropriate mockable instance. When looking at code, remember that the new operator is a static dependency - there are other good reasons to avoid its use in non-factory objects, too. – kyoryu Dec 24 '09 at 03:22
  • Can someone provide an example of what is meant by this answer. – Stephen Price Jun 01 '16 at 08:08
  • @StephenPrice: In class constructor inject factory (IMyDisposableFactory MyDisposableFactory) then in public bool Foo() { using (IMyDisposableClass client = MyDisposableFactory.CreateCl()) { return client.SomeOtherMethod(); } } – Leszek P Oct 12 '16 at 11:07
  • 11 years later, I would say that your tests probably shouldn't test methods, they should test behaviours of the system. Outside in > inside out testing. – mcintyre321 Feb 12 '20 at 11:56
18

If you already have your code and are asking how to test it, then you're not writing your tests first...so aren't really doing TDD.

However, what you have here is a dependency. So the TDD approach would be to use Dependency Injection. This can be made easier using an IoC container like Unity.

When doing TDD "properly", your thought processes should run as follows in this sort of scenario:

  • I need to do a Foo
  • For this I will rely on an external dependency that will implement an interface (new or pre-existing) of IMyDisposableClass
  • Therefore I will inject an IMyDisposableClass into the class in which Foo is declared via its constructor

Then you would write one (or more) tests that fail, and only then would you be at the point where you were writing the Foo function body, and determine whether you needed to use a using block.

In reality you might well know that yes, you will use a using block. But part of the point of TDD is that you don't need to worry about that until you've proven (via tests) that you do need to use an object that requires this.

Once you've determined that you need to use a using block you would then want to write a test that fails - for example using something like Rhino Mocks to set an expectation that Dispose will get called on a mock object that implements IMyDisposableClass.

For example (using Rhino Mocks to mock IMyDisposableClass).

[TestFixture]
public class When_calling_Foo
{
    [Test]
    public void Should_call_Dispose()
    {
        IMyDisposableClass disposable = MockRepository
                                        .GenerateMock<IMyDisposableClass>();

        Stuff stuff = new Stuff(disposable);

        stuff.Foo();

        disposable.AssertWasCalled(x => x.Dispose());
    }
}

Class in which your Foo function exists, with IMyDisposableClass injected as a dependency:

public class Stuff
{
    private readonly IMyDisposableClass _client;

    public Stuff(IMyDisposableClass client)
    {
        _client = client;
    }

    public bool Foo()
    {
        using (_client)
        {
            return _client.SomeOtherMethod();
        }
    }
}

And the interface IMyDisposableClass

public interface IMyDisposableClass : IDisposable
{
    bool SomeOtherMethod();
}
SteveC
  • 15,808
  • 23
  • 102
  • 173
Richard Ev
  • 52,939
  • 59
  • 191
  • 278
  • 1
    I'm sorry Richard but your answer is not very helpful. I've written a lot of DI code and used many different Inversion of Control containers including Unity. I'm working on legacy code that has only integration tests. I like mcintyre321 answer where he suggests to use a factory. It's very helpful I can implement it. If you read my question completely you would read "Sometimes I choose not to use using statement and Dispose an object manually." – Vadim Dec 23 '09 at 16:41
  • I have modified the question to make it clearer that this is testing existing code, not TDD. – Jay Bazuzi Dec 23 '09 at 17:15
  • TBH it's pretty much the same answer I gave, except I'd have the constructor of Stuff like Stuff(Func myDisposableFactory) – mcintyre321 Dec 23 '09 at 17:27
  • @mcintyre: Do you do that for all injected dependencies, and then use the injected factory to instantiate your dependencies only when required? – Richard Ev Dec 23 '09 at 17:54
  • @Richard, my original comment was written before you edited your answer with the code sample. It's definitely helpful; however mcintyre321, was first. +1 – Vadim Dec 23 '09 at 18:11
  • 2
    @Richard, I only inject a factory Func (or a real Factory interface) as opposed to the dependency if the class has to manage the whole lifecycle of the dependency (e.g. create it and destroy it) or create multiple instances. See 'auto-generated-factories' in AutoFac 2 for a nice way for this to work (http://code.google.com/p/autofac/wiki/NewInV2) – mcintyre321 Dec 24 '09 at 10:08
  • 2
    What happens when someone calls `Foo()` twice for the same instance of `Stuff`? – Seph Sep 03 '13 at 11:29
  • @Seph - If that was a requirement then my approach would not be a good one. – Richard Ev Sep 03 '13 at 12:42
6

Your question doesn't make sense. If you are using TDD, then you should already have a test for what you have written. Requirements, then tests, then design, then development. Either your code passes your tests, or it doesn't.

Now, if your question is how to unit test the above piece of code, then that's another question completely, and I think the other posters have answered it up there.

Sometimes I think there are more buzzwords than developers :)

Larry Watanabe
  • 10,126
  • 9
  • 43
  • 46
  • 2
    Amen. It's incredible to watch people consistently struggle with the wrong tool (regex, LINQ) or the wrong approach (DDD) because it's "hot" and they just want to be "cool." Plus one. – jason Dec 23 '09 at 17:30
2

Wrapper methods like that aren't unit-testable, because you can't specify the relevant preconditions or post-conditions.

To make the method testable, you'll have to pass an IMyDisposableClass instance into the method or into the class hosting Foo (and make the host class itself implement IDisposable), so you can use a test double instead of the real thing to verify any interactions with it.

Jeff Sternal
  • 47,787
  • 8
  • 93
  • 120
0

Your question doesn't make sense. If you are doing TDD, then the method that you posted is already fully tested, otherwise it couldn't even exist in the first place. So, your question doesn't make sense.

If, on the other hand, the method that you posted does already exist, but isn't fully tested, then you aren't doing TDD anyway, and your question about TDD doesn't make sense, either.

In TDD, it is simply impossible for untested code to exist. Period.

Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
0

You could also change the method signature to allow passing in a mock for unit testing. This would provide an alternative to using a factory, which would also need to be unit tested. DI into the method as opposed to the class constructor may be preferable here.

public bool Foo(IMyDisposableClass mock = null)
{
    using (IMyDisposableClass client = mock ?? new MyDisposableClass())
    {
        return client.SomeOtherMethod();
    }
}
B2K
  • 2,541
  • 1
  • 22
  • 34
-1

If you are testing Foo, then you should be looking at the output of Foo, not worrying about the disposal of the class it is using internally.

If you want to test MyDisposableClass' dispose method to see if it is working, that should be a separate unit test built against MyDisposableClass.

You don't need to unit test the using { } block, since that is part of the language. You either trust that it's working, or don't use C#. :) I don't see the need to write a unit test to verify that Dispose() is being called.

womp
  • 115,835
  • 26
  • 236
  • 269
  • I don't want to test MyDisposableClass I want to mock it. Jeff Sternal and mcintyre321 bellow have good suggestions for me to try. – Vadim Dec 23 '09 at 16:16
  • Nobody wants to test the using{} block. The using{} block presents a dependency that can't be injected since the instantiation of an object using the using{} block must be done In-Line. And since that dependency is typically to a persistence layer or some code that unmanaged at some point, it's important to DI it with a mock. So the question is, how do you DI a Using{} block to mock out the dependency. – Suamere Mar 04 '14 at 23:21
-1

Without a specification for Foo, how can we say how to test it?

  1. Get the specification for Foo.
  2. Write tests to ensure that it meets all specifications and requirements (or a reasonable subset- some functions could require practically infinite amounts of data to test).

I believe you have a second, implicit question in there - which is how to test that use of your MyDisposableClass correctly Disposes of the object when it is freed by exiting an using clause. This is a separate test issue, and shouldn't be combined with the test of Foo, since the specification of Foo shouldn't reference implementation specific details such as the use of your MyDisposabeClass.

I think the other posters have answered this question, so I won't further elaborate.

Larry Watanabe
  • 10,126
  • 9
  • 43
  • 46