Rachit Jain
Rachit Jain

Reputation: 302

Mocking Java objects in my target where target has no setters available

The situation is that I have to write Unit test for one of Java class. That java class in the constructor creates object of another class(3rd party), no so setter available for setting the 3rd party class.

I do not have the 3rd party class available with me, so would like to mock it. So is it possible by Mockito or any other framework or any other suggestion.

One option I see is to self create that 3rd party class (with same package info) and provide called functions returning whatever I wish and provide class path where these mocked will exist.

Upvotes: 3

Views: 1173

Answers (5)

Rachit Jain
Rachit Jain

Reputation: 302

Just to ensure this thread is closed, I ultimately used PowerMock.

It helped me to mock behavior of private functions and static functions of other classes/objects that were used by the Test candidate object.

Upvotes: 0

unigeek
unigeek

Reputation: 2826

I like JMockit for this (and mocking generally).

import mockit.Mocked;
import mockit.NonStrictExpectations;
...
public class SubjectTest {
    ...
    @Mocked ThirdPartyClass thirdPartyObject;
    ...
    @Test
    public void should_do_whatever() {
        // arrange
        new NonStrictExpectations() {{
            thirdPartyObject.someMethod(); result = <your desired output>;
        }};
        // act
        ...
        // assert
        ...
    }
}

Upvotes: 0

beresfordt
beresfordt

Reputation: 5222

You could overload your constructor so you can pass in your mocked version of the ThirdPartyClass:

public class MyClass {
    private ThirdPartyClass thirdPartyObject;
    public MyClass() {
        this.thirdPartyObject = new ThirdPartyClass();
    }

    public MyClass(ThirdPartyClass thirdPartyObject) {
        this.thirdPartyObject = thirdPartyObject;
    }
}

public class MyClassTest {
    @Test
    public void someTest() {
        ThirdPartyClass thirdPartyObject = Mockito.mock(ThirdPartyClass.class);
        MyClass underTest = new MyClass(thirdPartyObject);

        ...
    }
}

Upvotes: 0

hoipolloi
hoipolloi

Reputation: 8044

You could use a spy to override behavior of the third-party instance.

For example, with Mockito it might look like this:

package org.foo;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.doReturn;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class FooTest {

    private static class ThirdParty {
        public String getName() {
            return "Third party implementation";
        }
    }

    @Spy
    private ThirdParty toTest = new ThirdParty();

    @Test
    public void test() {
        // Arrange
        doReturn("Hello").when(toTest).getName();

        // Act
        final String name = toTest.getName();

        // Assert
        assertEquals("Hello", name);
    }
}

Or you can use a standard mock if you don't actually require any of the third-party behavior:

@Mock
private ThirdParty toTest;

@Test
public void test() {
    // Arrange
    doReturn("Hello").when(toTest).getName();

    // Act
    final String name = toTest.getName();

    // Assert
    assertEquals("Hello", name);
}

Upvotes: 1

GermaineJason
GermaineJason

Reputation: 589

You could create a subclass of the 3rd party class from within your unit test class and override the relevant methods.

private class TestClass extends 3rdParty {

    public TestClass() {
        super();
    }

    @Override
    public String myMethod() {
        return "";
    }
}

So in your unit test you create the subclass object instead of the 3rd Party one.

 TestClass test = new TestClass();
 System.out.println(test.myMethod());

Upvotes: 1

Related Questions