java.lang.NoSuchMethodError: javax.servlet.http.HttpServletRequest.isAsyncStarted() при использовании Mockito с Junit
Я пытаюсь промокнуть ногами от TDD. Я пытаюсь написать тестовые примеры для контроллеров, использующих Mockito в сочетании с MockMvc и Junit.
Но я получаю ошибку во время выполнения, в результате чего мой тест не пройден. Сначала я столкнулся с проблемой при инициализации экземпляра MockMvc в настройке из-за сбоя при поиске javax.servlet.SessionCookieConfig
,
Это я решил, загрузив javax.servlet
API и настройки его в пути сборки проекта, но потом я сталкиваюсь с
java.lang.NoSuchMethodError: javax.servlet.http.HttpServletRequest.isAsyncStarted()
при использовании perform()
на экземпляре MockMvc.
Может кто-нибудь сказать мне, что делать с такого рода зависимостями, поскольку я думаю, что это происходит из-за несовместимого сервера servlet-api и javax.servlet api.
РЕДАКТИРОВАТЬ: я публикую код, который я использую для модульного тестирования, но я не думаю, что это поможет, но на всякий случай:
@RunWith(MockitoJUnitRunner.class)
public class MyControllerTest {
@InjectMocks
private MyController myController = new MyController();
@Mock
private MyService myService = new MyServiceImpl();
private MockMvc mockMvc;
@Before
public void setUp(){
this.mockMvc = MockMvcBuilders.standaloneSetup(myController).build();
}
@Test
public void testList() throws Exception{
A a = new A();
a = createMockClassA();
Mockito.when(myService.getServiceForA(Mockito.anyMapOf(String.class, String.class))).thenReturn(a);
MvcResult result = this.mockMvc.perform(get("/somePath/")).param("someExpectedParam","value").andReturn();
System.out.println(result.getResponse().getContentAsString());
}
private static A createMockClassA(){
A a = new A();
a.setId(i);
a.setTitle("mock-" + i);
return a;
}
}
6 ответов
Это очень похоже на неправильную версию API сервлета в пути к классам.
Проверьте когда isAsyncStarted
был добавлен в API и убедитесь, что тот, на который вы ссылаетесь в вашем class path, имеет по крайней мере ту версию или выше.
Чтобы найти место, откуда приходит "неправильная" версия класса, вы можете использовать
-verbose:class
Аргумент в пользу Java. В нем будут перечислены все загруженные классы, и если я правильно помню, откуда они загружаются. См. http://docs.oracle.com/javase/7/docs/technotes/tools/windows/java.html для получения подробной информации.
Это происходит, когда ваши среды разработки и производства используют разные версии API сервлетов.
При сборке с tomcat7(например) он поддерживает сервлет 3 и, следовательно, вы не получите никакой ошибки.
Делая то же самое на более низкой версии Tomcat, он выдаст ошибку.
Решение:
Либо обновите одну из сред для поддержки сервлета 3, либо просто понизьте код, чтобы использовать сервлет 2.5.
Сообщение об ошибке означает, что в вашем пути к классам установлена неверная версия API сервлета.
Если вы используете Gradle, выполните
gradle dependencies
проанализируйте дерево зависимостей и исключите зависимости 'servlet-api' версии ниже 3.0. Вы можете сделать следующее, чтобы исключить
compile ('javax.servlet:jsp-api:2.0'){
exclude module : 'servlet-api'
}
Может быть несколько зависимостей, которые дополнительно включают servlet-api-2.x. Исключить все
У меня была похожая проблема, некоторые из моих тестов Junit не работали (по идее intellij), и я также получал java.lang.NoSuchMethodError: javax.servlet.http.HttpServletRequest....
для этих юнит-тестов. Когда я пытаюсь скомпилировать весь проект, используя gradle, из каталога через командную строку с помощью команды gradle clean build
тогда код был успешно скомпилирован. Принимая во внимание, что проблема была с тестами Junit в идее Intellij, они показывали вышеупомянутую ошибку. Я просто изменил свою версию Gradle с 3.4.1 на 2.1.3. Я не знаю, почему сейчас мои тесты Junit компилируются, а мой код компилируется как через intellij, так и через командную строку. Та же проблема возникла с другим моим коллегой, и он также изменил версию Gradle с 4 на какую-то версию 2. Проблема была решена.
Я нашел решение для моей ошибки. Фактический api сервлета, который был получен, был gwt-servlet.jar, а сервлет-api в gwt-servlet.jar был более старой версии. Таким образом, я сконфигурировал путь сборки, чтобы во время сборки проект указывал на последний сервлет-API.
Что касается правильного ответа, я думаю, что мой голос переходит к Йенсу, так как он действительно дал решение, самое близкое согласно сценарию.
Спасибо всем.:)
Я решаю эту проблему, добавляя в Java путь сборки Tomcat в качестве библиотеки времени выполнения сервера