Reputation: 211
I'm trying to provide a clean Unit Test for a Controller of mine. This Controller has a Service as dependency and this Serviceh has a Datasource as dependency.
The test looks like this:
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration
public class ContentActionWebServiceControllerTest {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Autowired
private MyService myService;
@Test
public void getRequestActionList() throws Exception {
when(...)
perform(...);
verify(...);
}
@Configuration
@ImportResource("...")
static class MyTestConfiguration {
@Bean
public MyService myService() {
return Mockito.mock(MyService.class);
}
}
}
And the MyService is something like
@Service
public class MyService {
@Autowired
private MyDataSource myDatasource;
...
}
Because MyService as an Autowired property MyDataSource, the context isn't initialized because it doesn't find any MyDataSource type for satisfying the @Autowired annotation of MyService. But why does it ever try to resolve this annotation? Is this is a mock?
Upvotes: 1
Views: 1944
Reputation: 13181
If it's supposed to be a unit test (and not an integration test) you don't even need to use Spring, you can do it all with JUnit+Mockito. Rather than @Autowire
ing dependencies from Spring context, you can simply create mocks of the support objects (via @Mock
) and inject them to the testee (via @InjectMocks
). I believe your code could be simplified to something (conceptually) like this:
@RunWith(MockitoJUnitRunner.class)
public class ContentActionWebServiceControllerTest {
@Mock
private Service mockServiceUsedByController;
@InjectMocks
private YourController testee;
@Test
public void getRequestActionList() throws Exception {
assertFalse(testee.getRequestActionList().isEmpty());
// etc.
}
}
Upvotes: 1
Reputation: 4649
Mockito does use cglib to create a new child class of MyService
(and override all methods with mock methods).
But still, the dependencies of the parent will be injected, because this is how Spring does it's job:
if you have a parent class with some @Autowired
fields, and a child class that inherits from this parent class, then Spring will inject the @Autowired
fields of the parent when instantiating the child. I guess it's the same behavior in your case.
If you use an interface for MyService
, then your problem will be solved.
Upvotes: 4