wazz
wazz

Reputation: 780

Use mock object in test method implementation

I have a question. There's a method with implementation using another objects. I'd like to test this method which will not using another objects invoking.

class Object1 {

    public void method1() {
        Object2 object2 = new Object2();
        String info = object2.getInfo();
        // ...
        // working with info, which I want to test
        // ...
    }

}

class Object1Test {
    @Test
    public void testMethod1() {
        Object1 object1 = new Object1();
        object1.method(); // want to run this method without invoking Object2
    }
}

Could you help me to understand how in junit while testing method1() can I mock the using of Object2 with something like Object2Mock?

Upvotes: 3

Views: 1439

Answers (4)

Michu93
Michu93

Reputation: 5687

Dependency injection should be applied:

public class Object1 {
    Object2 object2;

    public Object1(Object2 object2) {
        this.object2 = object2;
    }

    public void method1() {
        String info = object2.getInfo();
    }

}

and in test:

import org.junit.runner.RunWith;
import org.mockito.*;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import org.junit.*;

@RunWith(MockitoJUnitRunner.class)
public class Object1Test {
    Object1 object1;
    @Mock
    Object2 mockedObject2;

    @Before
    public void setUp(){
        object1 = new Object1(mockedObject2);
    }

    @Test
    public void testMethod1() {
        Mockito.when(mockedObject2.getInfo()).thenReturn("Mocked response");

        object1.method1();
    }
}

In code which you provided only PowerMockito is solution but it's strongly not recommended.

Upvotes: 0

jfcorugedo
jfcorugedo

Reputation: 10051

Unfortunately your code is not prepare for pure unit testing.

The reason is that Object1 is creating an instance of Object2. There is no way to easily mock a new statement.

I recommend you to use another approach (dependency injection, receive the object as a parameter or in the constructor).

If you can't change the relation between Object1 and Object2, you can use PowerMock.

Take a look at: https://github.com/jayway/powermock/wiki/MockConstructor

But take into account that PowerMock should be used only when there is no alternatives. The use of PowerMock denotes a bad design.

Upvotes: 1

Manish
Manish

Reputation: 3968

The issue is you are creating a new object within your method. You can refactor your code like this:

class Object1 {

    public void method1() {
        Object2 object2 = getObject2();
        String info = object2.getInfo();
        // ...
        // working with info, which I want to test
        // ...
    }
    public Object2 getObject2() {
     return new Object2();
    }

With the above code, now you can mock the method getObject2() while testing method1().

Upvotes: 1

ninja.coder
ninja.coder

Reputation: 9648

You need to make some changes to your class to achieve what you are trying to do.

class Object1 {
    private Object2 object2 = new Object2();

    /* Setter Method for Object2 */
    public void setObject2(Object2 object2) {
         this.object2 = object2;
    }

    public void method1() {
        String info = object2.getInfo();
        // ...
        // working with info, which I want to test
        // ...
    }
}

Now you just have to call your setter-method with the mocked object for Object2.

class Object1Test {
    @Test
    public void testMethod1() {
        Object1 object1 = new Object1();
        object1.setObject2(/* Pass your mocked object here */);
        object1.method(); // want to run this method without invoking Object2
    }
}

You can also use Mockito or JMock to create the object mocks. You can simply tell Mockito to return the dummy response whenever getInfo() is invoked on Object2. For example,

Mockito.when(mockedObject2.getInfo()).thenReturn("Dummy Response");

Upvotes: 1

Related Questions