Stephane Toussaint
Stephane Toussaint

Reputation: 211

Context initialization issue for controller Unit testing with Spring 3.2 and Mockito

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

Answers (2)

kryger
kryger

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 @Autowireing 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

rcomblen
rcomblen

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

Related Questions