Spring - Как правильно использовать @Autowired, чтобы контроллер / MockMvc не был нулевым? - PullRequest
0 голосов
/ 21 декабря 2018

Я пытаюсь запустить некоторые юнит-тесты и сталкиваюсь с проблемой, которая, я уверен, проистекает из недопонимания об автопроводке.У меня есть класс модульного тестирования, в котором я пытаюсь использовать @Autowired на контроллере MockMvc и REST - оба из которых заканчиваются нулевым.

Я видел, как некоторые источники пытаются объяснить, почему это может(включая этот пост More of Less и полезный пост StackOverflow , который дал мне некоторое представление, но не полностью помог мне решить мою проблему).

Нижеявляется релевантным исходным кодом из примера проекта, созданного мной для воссоздания этой проблемы.

ManagerControllerTest.java

@RunWith(SpringRunner.class)
@WebMvcTest(ManagerController.class)
public class ManagerControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private Manager manager;

    @Autowired
    private ManagerController controller;

    @Test
    public void controllerNotNull() throws Exception {
        assertThat(controller).isNotNull();
    }

    @Test
    public void testStoreSomething() throws Exception {
        String path = "/manager/store-something/";

        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(path)
                    .characterEncoding("UTF-8")
                    .contentType(MediaType.APPLICATION_JSON);

        MvcResult result = mockMvc.perform(builder).andReturn();
        assertEquals(HttpStatus.CREATED, result.getResponse().getStatus());
    }
}

Результаты теста controllerNotNull() в

java.lang.AssertionError: Ожидается, что фактический не будет нулевым

Хотя, что любопытно, когда я создал новый проект Gradle на Java и импортировал мой пример кода из этого поста вэто, controllerNotNull() проходит.

И testStoreSomething() приводит к

java.lang.NullPointerException в com.example.sandbox.rest.ManagerControllerTest.testStoreSomething (ManagerControllerTest.java:46)

И здесь кроется вопрос: что я неправильно понимаю?Что я делаю неправильно?Я могу удалить @Autowired из контроллера и просто создать его с помощью new ManagerController(), но у меня остается проблема MockMvc.

ManagerController.java

@Controller
@RequestMapping(value = "/manager/")
public class ManagerController {
    Manager manager = new Manager(new StringStorage());

    @PostMapping(value = "store-something")
    private ResponseEntity<?> storeSomething(String str) {
        manager.storeSomething(str);
        return new ResponseEntity<>(CREATED);
    }
}

Manager.java

public class Manager {
    private final Storage storage;

    public Manager(Storage storage) {
        this.storage = storage;
    }

    public void storeSomething(String str) {
        storage.store(str);
    }
}

Storage.java

public interface Storage {
    void store(String str);
}

StringStorage.java

public class StringStorage implements Storage {
    Map<String, String> stringMap;

    @Override
    public void store(String str) {
        stringMap.put(str, str);
    }
 }

Application.java

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

build.gradle Который был отредактирован из исходного поста (для использования JUnit4), но проблема остается.

repositories {
    jcenter()
}

apply plugin: 'java'
apply plugin: 'eclipse'

dependencies {
 compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.0.0.RELEASE'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-tomcat', version: '2.0.0.RELEASE'

    testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '2.0.0.RELEASE'
    testImplementation 'org.junit.jupiter:junit-jupiter-api:4.0.0'
    testImplementation 'org.junit.jupiter:junit-jupiter-params:4.0.0'
    testCompile group: 'org.mockito', name: 'mockito-core', version: '2.17.0'
    testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: "4.0.0"
    testCompile group: 'org.junit.platform', name: 'junit-platform-launcher', version: "1.3.1"
}

Ответы [ 2 ]

0 голосов
/ 21 декабря 2018
@RestController
@RequestMapping(value = "/manager")
public class ManagerController {

    @Autowired
    Manager manager;

    @PostMapping(value = "/store-something")
    private ResponseEntity<?> storeSomething(String str) {
        manager.storeSomething(str);
        return new ResponseEntity<>(CREATED);
    }
}


@Component
public class Manager {

    @Autowired
    private Storage storage;

    public void storeSomething(String str) {
        storage.store(str);
    }
}


public interface Storage {
    void store(String str);
}

@Service
public class StringStorage implements Storage {
    Map<String, String> stringMap = new HashMap<>();

    @Override
    public void store(String str) {
        stringMap.put(str, str);
    }
 }




@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

Тестовый класс:

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class ApplicationTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void shouldReturnDefaultMessage() throws Exception {
        this.mockMvc.perform(post("/manager/store-something")).andDo(print()).andExpect(status().isOk())
                .andExpect(content().string(containsString("Hello World")));
    }
}
0 голосов
/ 21 декабря 2018

добавить аннотацию AutoConfigureMockMvc в свой тестовый класс

@RunWith(SpringRunner.class)
@AutoConfigureMockMvc
public class ManagerControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private Manager manager;

    @Autowired
    private ManagerController controller;

    @Test
    public void controllerNotNull() throws Exception {
        assertThat(controller).isNotNull();
    }

    @Test
    public void testStoreSomething() throws Exception {
        this.mvc.perform(get("/manager/store-something/"))
        .contentType(MediaType.APPLICATION_JSON)
        .andExpect(status().isOk())

    }

В качестве альтернативы вы также можете использовать TestRestTemplate с @SpringBootTest (webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

...