Shaun
Shaun

Reputation: 3895

JUnit mocking with Mockito, EasyMock, etc

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

Upvotes: 4

Views: 6653

Answers (6)

Rogério
Rogério

Reputation: 16380

Yes, there is a way, as shown by the following JMockit test:

public void testDoSomething(final SomeObject mock)
{
    new ClassToTest().doSomething();

    new Verifications() {{ mock.doSomethingElse(); }};
}

No need to refactor code under test to use a wrapper, DI, etc; simply mock whatever you need to be mocked.

Upvotes: 2

Boris Pavlović
Boris Pavlović

Reputation: 64632

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();
    }
}

Upvotes: 2

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();

Upvotes: 0

Buhb
Buhb

Reputation: 7149

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.

Upvotes: 0

Thomas
Thomas

Reputation: 4999

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.

Upvotes: 1

Jeroen Rosenberg
Jeroen Rosenberg

Reputation: 4682

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.

Upvotes: 2

Related Questions