Reputation: 3471
I have a special case, where I have to mock some fields and use both @Mock and @Spy for my class, which is under test, because at some tests I need to change behaviour of it's own methods. I use @InjectMocks for constructor. It looks like this:
Test class:
@RunWith(MockitoJUnitRunner.class)
public class ServiceTest {
@Mock
private SomeObject usedAsNonFinal;
@Mock
private SomeObject usedAsFinal;
@Spy
@InjectMocks
private ServiceTest service = new ServiceTest(usedAsNonFinal, usedAsFinal);
@Before
public void setup() {
when(usedAsNonFinal.someMethod(Matchers.any()))
.thenReturn(someObject);
when(usedAsFinal.someMethod(Matchers.any()))
.thenReturn(someObject);
doReturn(someObject).when(service).someMethod(Matchers.any());
}
}
Service, which is under test:
@Service
public class Service {
private SomeObject usedAsNonFinal //injects correctly
private final SomeObject usedAsFinal; //null - not injected
@Autowired
public Service (SomeObject usedAsNonFinal, SomeObject usedAsFinal){
this.usedAsNonFinal = usedAsNonFinal;
this.usedAsFinal = usedAsFinal;
}
//some methods to mock depending on test
}
The problem is - as commented in code - that final field is not getting injected and it's null. When I remove final keyword it gets injected correctly and all tests are working as expected. I tried some tricks from other topics - also using reflection, but nothing seems to be workking in this particular case.
Upvotes: 2
Views: 3979
Reputation: 934
Did you try don't instantiate ServiceTest
in test?
@InjectMocks should do it for you. Try just
@Spy
@InjectMocks
private ServiceTest service;
Upvotes: 3