Home > Back-end >  Semi-integration testing using mocks and application context
Semi-integration testing using mocks and application context

Time:08-15

I need to write an e2e test on REST level, that sends real requests. So I want to use application context instead of mocking beans.

RestController.class has an autowired MyService.class, and this MyService.class is dependent on two repository classes. So I tried to mock repositories and inject them in the real Service in the following way:

@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = MyService.class)
@AutoConfigureMockMvc
class MyControllerTest {

  @Mock private MyRepository repository;
  @Mock private AnotherRepository anotherRepository;
  @Autowired @InjectMocks private MyService service;
  @InjectMocks private MyController controller;

  @RepeatedTest(1)
  void someTest() throws Exception {
    MockHttpServletResponse response =
        mvc.perform(...); assertThat(...);
  }
}
@Service
@RequiredArgsConstructor
public class MyService {
  private final MyRepository repository;
  private final AnotherRepository another; ...}

But I get the following error: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'myRepository'

I also tried to use @ContextConfiguration(classes = {MyConfig.class }) with no success:

@EnableWebMvc
@Configuration
public class MyConfig {
  @Autowired private MyService service;
  @Mock private MyRepository repository;
  @Mock private AnotherRepository another;
}

Is there something I'm missing?

CodePudding user response:

First off you should not use @Mock which is relevant for plain unit testing with mockito, use @MockBean instead. @MockBean "belongs" to the spring universe, it will create a bean (backed by mockito after all) but also will place it into the application context. If there is another bean of this type - it will substitute it.

I also don't think you should use @ExtendWith because @SpringBootTest in the relatively recent spring boot versions already has it defined (check the source code of @SpringBootTest annotation to make sure that's the case indeed.

Now other mistakes are more complicated. To start with you don't need a spring boot test at all here. It also has a wrong parameter actually (which should point on a configuration class).

You should use @WebMvcTest instead. It seems that you only want to test the controller, and mock the service. @SpringBootTest in general tries to mimick the loading of the whole application, whereas the @WebMvcTest only tests a web layer. BTW, with this approach you don't need to even mock the Repository class because the controller will use the mock of the service, and since you don't load the whole application context there is no need to define a repository at all (the service being a mock doesn't use it anyway)

CodePudding user response:

Add @RunWith(SpringRunner.class) to class MyControllerTest

@RunWith(SpringRunner.class)
class MyControllerTest {

 
}
  • Related