Сбой теста Spring MVC

Я пытаюсь запустить тест Spring MVC, но продолжаю получать это исключение.

org.springframework.web.util.NestedServletException: ошибка обработки запроса; вложенным исключением является java.lang.NullPointerException

Исключение возникает из-за того, что автосвязанная зависимость,

    @Autowired
    private AccountService accountService;

не вводится в тесте (отлично работает вне теста).

Кто-нибудь может мне с этим помочь. Вот мой код:

// Класс AccountControllerITest

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MockServletContext.class)
@WebAppConfiguration
public class AccountControllerITest {

private MockMvc mvc;

ObjectMapper om;

@Before
public void setUp() throws Exception {
    mvc = MockMvcBuilders.standaloneSetup(new AccountController()).build();
}

@Test
public void getAccounts() throws Exception {
    MvcResult mvcResult =     mvc.perform(MockMvcRequestBuilders.get("/api/accounts"))
            .andExpect(status().isOk())
            .andReturn();
}    
}

}

//Контроллер учетных записей

@RestController
@RequestMapping("/api/accounts")
public class AccountController {

@Autowired
private AccountService accountService;

@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<Set<AccountInfo>> getAccounts(@RequestParam(value = "firstName", required = false) String firstName,
                                                    @RequestParam(value = "surName", required = false)  String surName) {
    Set<AccountInfo> accounts = accountService.getAccounts(firstName, surName);
    return new ResponseEntity<>(accounts, HttpStatus.OK);
}

}

Спасибо за помощь!


person kellzerIrl    schedule 02.09.2015    source источник
comment
Используйте внедрение конструктора.   -  person chrylis -cautiouslyoptimistic-    schedule 02.09.2015


Ответы (2)


Поскольку вы используете автономную установку: mvc = MockMvcBuilders.standaloneSetup(new AccountController()).build();. Если вы создаете контроллер через new AccountController(), у Spring не будет возможности внедрить accountService, поскольку он не контролирует создание и подключение экземпляров.

У вас есть два варианта:

  1. Переключите свой тест на модульный тест и вообще не используйте SpringJUnit4ClassRunner и MockServletContext. Вы можете использовать @InjectMocks для внедрения частного accountService:

    public class AccountControllerITest {
    
        private MockMvc mvc;
    
        ObjectMapper om;
    
        @Mock
        private AccountController accountController = new AccountController();
    
        @InjectMocks
        private AccountService accountService = new Mockito.mock(AccountService.class);
    
        @Before
        public void setUp() throws Exception {
            mvc = MockMvcBuilders.standaloneSetup(accountController).build();
        }
    

    Существует также улучшение, которое вы можете применить к своему контроллеру. Замените внедрение поля на внедрение конструктора, и вы можете передать accountService контроллеру через конструктор в тесте. Таким образом, вам вообще не нужно использовать @InjectMocks.

  2. Используйте настройку webAppContext:

    @Autowired
    private WebApplicationContext webApplicationContext;
    
    @BeforeMethod
    public void init() {
        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }
    
person luboskrnac    schedule 02.09.2015
comment
@Ikmac- спасибо за ответ. Не могли бы вы объяснить, в чем проблема, пожалуйста, я не понимаю. Спасибо - person kellzerIrl; 02.09.2015
comment
Спасибо за вашу помощь. Я выбрал вариант 2. Теперь я понимаю, в чем была проблема. Спасибо за объяснение! - person kellzerIrl; 02.09.2015

Вам нужно настроить свой тест для внедрения ваших автосвязанных свойств. См. следующий блок кода:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class AccountControllerITest {

    // ... your test code

    @Configuration
    public static class YourConfiguration {

        @Bean
        AccountService accountService() {
            // init and return your AccountService
        }
    }
}

Вы можете инициализировать AccountService с помощью Mockito.

person schrieveslaach    schedule 02.09.2015
comment
Это не помогает, поскольку он смешивает интеграцию с модульным тестом. - person luboskrnac; 02.09.2015