0

I'd like to perform an integration test. My current approach:

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class)
@AutoConfigureMockMvc
@TestPropertySource(locations = "classpath: application-test.yml")
public class UserControllerIntegrationTest {

    @Autowired
    MockMvc mockMvc;

    @Test
    @DisplayName(" sda")
    public void test1(){

        System.out.println();
    }

}

I placed @AutoConfigureMockMvc, but the MockMvc object remains null

Schroedinger
  • 301
  • 6
  • 17

2 Answers2

1

I couldn't really understand what was the purpose of such a test, let me explain...

Usually MockMvc is used to test the web layer of the application.

This means that under the hood spring runs "something" that can mimic the requests sent to controllers so that you could check that the annotations are placed correctly, the conversion of objects is done in a proper way, etc. In other words its like testing the controller, but it has nothing to do with services, DAOs, etc. Usually the references to the services from controller can be annotated with @MockBean so that spring will create a stub for services and you'll be able to describe the interactions. Other things like DAOs should never be referenced from controllers anyway (don't them ? ;) ) but in general the same pattern of mocking out these dependencies is applicable here.

Technically its done as follows: The web mvc test (when annotated properly) doesn't load the whole application context but a "slice" of it - only beans relevant for the web layer.

Now @SpringBootTest annotation does something different. Its designed especially for spring boot application and allows to mimic the whole spring application load. Out of my head (maybe other colleagues will enrich this list), it "adds up" to the regular application context starting:

  • Properties configuration management
  • Starters (auto-configuration modules)
  • Package structure specific scanning for Beans and configurations

Bottom line, it allows starting Spring Boot Test out of some specific configuration or the whole application, it has nothing to do with a web layer only.

So, what I don't understand is what exactly is expected to be tested here. If your goal is testing a web layer, then you don't have to use Spring Boot annotation (in addition to what I've already explained, spring boot test takes much more time to load)

If your goal is testing the microservice at a whole or sometimes a specific slice of it, then you can use @SpringBootTest` annotation.

Mark Bramnik
  • 39,963
  • 4
  • 57
  • 97
  • It might help https://stackoverflow.com/questions/55276555/when-to-use-runwith-and-when-extendwith – Joydeep Aug 20 '19 at 08:05
  • It's a monolith. The goal is to test REST enpoints methods through all layers – Schroedinger Aug 20 '19 at 08:06
  • If you want to test the flow, don't use MockMvc... Again, MockMvc is used to test only RestControllers but it doesn't load the service layer at all. – Mark Bramnik Aug 20 '19 at 08:08
  • Not sure, what should be used instead? – Schroedinger Aug 20 '19 at 08:10
  • Only SpringBootTest... It will run the whole app (regardless whether is a monolith or microservice). MockMvc = Mock Server with access to controllers and no access to Business Logic Layer. SpringBootTest = whole application. You can inject controllers into the test (Autowire) and call them as if they're regular java classes. or you can even start a whole web server and call through real http or something. – Mark Bramnik Aug 20 '19 at 08:13
  • I need mockMvc to perform rest methods – Schroedinger Aug 20 '19 at 08:15
  • No you don't :) Again, MockMvc is not an http client. Its a test tool given by spring developers to test the controller. – Mark Bramnik Aug 20 '19 at 08:17
  • Isn't a restcontroller a type of controller? for example https://www.tutorialspoint.com/spring_boot/spring_boot_rest_controller_unit_test.htm how would you comment this? – Schroedinger Aug 20 '19 at 08:21
  • Yes, it is indeed. you can use mock mvc to test controller/rest-controller but only controllers. When you use mock mvc it doesn't load the service beans at all, only controller beans. – Mark Bramnik Aug 20 '19 at 08:24
  • It it helps you can see that it resembles https://reflectoring.io/spring-boot-data-jpa-test/ with the difference that this one used to load "slice" that is relevant to database (JPA, spring data, etc) and web mvc loads the "slice" of web. If you need more clarifications - feel free to move this discussion to chat – Mark Bramnik Aug 20 '19 at 08:26
  • but I should be able to autowire controller ->service ->repository, but it doesn't work. it remains null too, the appropriate bean is found in compile time as IDE shows though – Schroedinger Aug 20 '19 at 08:28
  • MockMvc nad SpringBootTest play role at runtime. With mock mvc you're not expected to get Services and Repositories as I've originally explained... Only a slice of controller. – Mark Bramnik Aug 20 '19 at 08:29
  • The thing is I've done it before in microservice application with the same configuration like that and it worked. By the way I know what's repository, service, controller unit testing ;) – Schroedinger Aug 20 '19 at 08:31
  • Maybe the configurations are different in this spring boot application. I didn't mean unit testing at all, both spring-boot-test and mock-mvc are integration testing tools... – Mark Bramnik Aug 20 '19 at 08:35
  • yes, I want to do an inegration test. Give me then please proper standard class schema. I thought @ AutoConfigureMockMvc + @ MockMvc and @ Autowiring Controller should be enough – Schroedinger Aug 20 '19 at 08:40
  • Nah, the configuration is the same, the thing is i didn;t exlude junit from spring boot test starter dependency, becuse there was other, older tests in junit4 in project and the problem arrived because of I annotated by accident a test method with @ Test annotation from junit instead of jupiter.. I came up with that becuase it worked with @RunWith but not @ ExtendWith from junit 5 – Schroedinger Aug 20 '19 at 08:54
0

If you annotate your test with @RunWith(SpringRunner.class) your mockMvc will not be null.

Spasoje Petronijević
  • 1,476
  • 3
  • 13
  • 27