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 {
}