Reputation: 81
I am trying to write JUnits for some class which is as follows
class C{
public C fun(D d){
// fetch some data from database using object of D
// do some operations on that data
// create an object of C using this data
// return that object of C
}
}
@Component
class toBeTested{
@Autowired private A a;
@Autowired private B b;
public C methodToBeTested(){
C c = new C(a.getD()).fun();
return c;
}
}
I want to test methodToBeTested() method. Please tell is there any way In which we can mock the method calls of object D present in class C while execution of fun() method. Or If there is some other easy way to handle this situation in mockito. All I have found until now is this Stack overflow but still I am not clear how to use this in my situation
Upvotes: 1
Views: 904
Reputation: 42441
If you use @Autowired
in class C, this C should be managed by Spring, otherwise the "autowiring magic of D inside C won't happen"
But if so, why do you create a new instance of C in class toBeTested
? It doesn't really make sence.
So you should:
@Component
on class C so that Spring will manage it.toBeTested
:@Component
class toBeTested{
@Autowired private A a;
@Autowired private B b;
@Autowired private C c;
public C methodToBeTested(){
return c.fun();
}
}
Its quite strange to see c.fun() that returns itself, is it a builder or something? Maybe you should make it 'prototype scope' and then the solution is slightly different, but since its not mentioned in the question, I don't have enough details so I'll leave the answer as is...
Update 1
Now when its clear that class C for reasons which are beyond the control of OPs is not managed by spring, there are two options:
Use PowerMock/Power Mockito if you have to preserve class toBeTested
in its current form (with new C() in the method to be tested
. This approach in general considered a bad practice use it only if you don't have another choice. These tools can mock the creation of object (new) and substitute C with some stub on the fly.
If you can change the class toBeTested
- use dependency injection:
public class ToBeTested {
@Autowired private A a;
@Autowired private B b;
@Autowired private CFactory cFactory;
public C methodToBeTested() {
return cFactory.create(a.getD()).fun();
}
}
interface CFactory {
C create(D d);
}
@Component
public class DefaultCFactoryImpl implements CFactory {
public C createC(D d) {
return new C(d);
}
}
This approach is much better because it allows to substitute the factory with the implementation that will create a mock of C or whatever you'll find appropriate for the test.
Upvotes: 2
Reputation: 2773
It's always better to use a constructor injection.
But if you don't want to refactor, you can use @InjectMocks
from mockito.
class ToBeTestedTest {
@Mock private A a;
@Mock private B b;
@InjectMocks ToBeTested toBeTested; // mockito will inject your mocks
@Before
public void setUpMocks() {
when(a.getSomeParameter()).thenReturn(new DummyObject())
}
}
Upvotes: 0