Farrukh Chishti
Farrukh Chishti

Reputation: 8437

Mock private wrapper/primitive/String field

My question is not this question. I want to mock private wrapper fields like Integer and String. Also, these fields are in an abstract super class.

public abstract class SuperSample
{
    private Integer var1;
    private String var2;

    private Service service;

    pubic boolean foo()
    {
          int a = service.doStuff(var1, var2);
          return subMethod(a);
    }

    protected abstract boolean subMethod(int var);

    public void setVar1(Integer var1)
    {
        this.va1 = var1;
    }

    public Integer getVar1()
    {
        return var1;
    }

    public void setVar2(String var2)
    {
        this.var2 = var2;
    }

    public String getVar2()
    {
        return var2;
    }

    public void setService(Service service)
    {
        this.service = service;
    }

    public String getService()
    {
        return service;
    }
}

public class Sample extends SuperSample
{
    protected boolean subMethod(int var)
    {
        return var%2==0?true:false;
    }
}

Spring.xml -

<bean id="superSample" class="SuperSample" abstract="true">
    <property name="var1" value="2" />
    <property name="var2" value="cool" />
</bean>

<bean id="sample" class="Sample" >
    <property name="service" ref="service" />
</bean>

In my junit I can't mock or spy var1 or var2. On spying/mocking var1, var2 I get the error:

org.mockito.exceptions.base.MockitoException: Cannot mock/spy class java.lang.Integer Mockito cannot mock/spy following: - final classes - anonymous classes - primitive types

I want to mock the line -

service.doStuff(var1, var2)

with something like-

@UnitTest
public class SampleTest
{
    @Mock 
    private Service service;

    private Integer var1 = 2
    private String var2 = "cool";

    @InjectMocks
    private Sample sample;  

    @Test
    public void test()
    {
        MockitoAnnotations.initMocks(this); 
        Mockito.when(service.doStuff(var1, var2)).thenReturn(5);
    }
}

Upvotes: 1

Views: 2752

Answers (3)

Jonathan S. Fisher
Jonathan S. Fisher

Reputation: 8817

Here you go, we created a JUnit extension to solve this precise problem.

https://github.com/exabrial/mockito-object-injection

Upvotes: 1

Nkosi
Nkosi

Reputation: 247088

Based on currently shown example the mock can be injected via the set member

@UnitTest
public class SampleTest {
    @Mock 
    private Service service;

    private Integer var1 = 2
    private String var2 = "cool";

    @Test
    public void test() {
        //Arrange
        MockitoAnnotations.initMocks(this);

        Sample sample = new Sample();
        sample.setService(service);
        sample.setVar1(var1);
        sample.setVar2(var2);          

        Mockito.when(service.doStuff(var1, var2)).thenReturn(5);

        //Act
        boolean actual = sample.foo();

        //Assert

        //...
    }
}

Ideally, the more SOLID design approach would be to refactor the subject class to use explicit dependency principle via constructor injection

public class Sample extends SuperSample {

    public Sample(Service service) {
        super.setService(service);
    }

    protected boolean subMethod(int var) {
        return var%2==0?true:false;
    }
}

Allowing any explicit dependencies to be injected

@UnitTest
public class SampleTest {
    @Mock 
    private Service service;

    private Integer var1 = 2
    private String var2 = "cool";

    @InjectMocks
    private Sample sample;  

    @Test
    public void test() {
        //Arrange
        MockitoAnnotations.initMocks(this); 

        sample.setVar1(var1);
        sample.setVar2(var2);  

        Mockito.when(service.doStuff(var1, var2)).thenReturn(5);

        //Act
        boolean actual = sample.foo();

        //Assert

        //... 
    }
}

Upvotes: 1

Lino
Lino

Reputation: 19926

You can simply inject the values yourself and then remove the @InjectMocks annotation. This can best be done in a setup method annotated with @Before so it gets executed for every test.

@Before
public void setup() {
    MockitoAnnotations.initMocks(this);
    sample = new Sample();
    sample.setVar1(1234);
    sample.setVar2("5678");
    sample.setService(service);
}

Upvotes: 1

Related Questions