views:

106

answers:

5

I'm trying to mock a method of an object inside the class I'm testing.

For instance

class ClassToTest {
   public doSomething () {
       SomeObject a = new SomeObject ();
       a.doSomethingElse ();
   }
}

Is there a way to mock the methods of the variable "a"? I'd like doSomethingElse to do nothing during testing. I'm currently using Mockito but I'm open to any mocking framework.

Thanks

+2  A: 

It's not possible to mock the reference "a" when it's declared as a local variable, as in your case. You could consider injecting the dependency to SomeObject, e.g. as a parameter of doSomething method. That way, you can inject a mock of SomeObject in your test instead.

One of the benefits of dependency injection is increased testability.

Jeroen Rosenberg
+1  A: 

I believe you can use EasyMock Class Extensions for EasyMock 2.5 or earlier, and apparently it is included in 3.0. See this part of the previous page for information on what you are trying to do. That said, I haven't personally tried to do that, so I don't know how well it will work.

Thomas
with EasyMock class extensions, you can mock classes where you can only mock interfaces without class extensions. However, you cannot mock references declared as local variables.
Jeroen Rosenberg
+2  A: 

With some refactoring it is possible, of course:

class SomeObject {
    public void doSomethingElse()
    {

    }
}

class ClassToTest
{
    private final SomeObject someObject;

    public void doSomething()
    {
        someObject.doSomethingElse();
    }

    public ClassToTest(SomeObject someObject)
    {
        this.someObject = someObject;
    }
}

class Test {
    @Test
    public void testDoSomething()
    {
        SomeObject someObject = Mockito.mock(SomeObject.class);
        new ClassToTest(someObject).doSomething();
        Mockito.verify(someObject, Mockito.atLeastOnce()).doSomethingElse();
    }
}
Boris Pavlović
Yes this was my thought as well. I just wasn't sure if mocking a local variable was possible (yet)
Shaun
A: 

If you want a new instance in each call, I'd suggest refactoring in the following way:

class ClassToTest {
   public doSomething () {
      SomeObject a = getInstance();
      a.doSomethingElse ();
   }
   protected SomeObject getInstance() {
      return new SomeObject();
   }
}

Then you can create a testclass extending ClassToTest, overriding the getInstance() method, with one supplying a mock object.

This is of course only viable if you are ok with exposing the getInstance() method, so I don't recommend it if the class is part of a public API. If this is the case, consider supplying a factory class using dependency injection.

Buhb
If you are going down this route I think I'd create a Provider (Factory) and inject that. A decent DI framework (like say Guice) will create the factory for you.
mlk
A: 
class ClassToTest {
    private SomethingElseInterface somethingElseDoer ;

    public ClassToTest(SomethingElseInterface somethingElseDoer) {
        this.somethingElseDoer = somethingElseDoer;
    }

    public doSomething () {
        somethingElseDoer.doSomethingElse();
    }
}

And where you use it:

SomethingElseInterface somethingElseDoer = ...; // in a test, this is where you mock it
ClassToTest foo = new ClassToTest(somethingElseDoer); // inject through constructor
foo.doSomething();
Christoffer Hammarström