Reputation: 8437
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
Reputation: 8817
Here you go, we created a JUnit extension to solve this precise problem.
https://github.com/exabrial/mockito-object-injection
Upvotes: 1
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
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