java.lang.NoSuchMethodError: javax.servlet.http.HttpServletRequest.isAsyncStarted() при использовании Mockito с Junit

Я пытаюсь намочить ноги с помощью TDD. Я пытаюсь написать модульные тестовые примеры для контроллеров, используя Mockito в сочетании с MockMvc и Junit.

Но я получаю ошибку времени выполнения, тем самым проваливая тест. Сначала я столкнулся с проблемой инициализации экземпляра MockMvc в настройке из-за невозможности найти файл javax.servlet.SessionCookieConfig.

Это я решил, загрузив API javax.servlet и настроив его на путь сборки проекта, но затем я столкнулся с

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

person Sourabh    schedule 20.05.2014    source источник


Ответы (6)


Это очень похоже на то, что у вас неправильная версия API сервлета в пути к классам.

Проверьте, когда isAsyncStarted был добавлен в API, и убедитесь, что тот, на который вы ссылаетесь в своем пути к классам, имеет по крайней мере эту версию или более позднюю.

Чтобы найти место, откуда исходит «неправильная» версия класса, вы можете использовать

-verbose:class

Аргумент в пользу Java. В нем будут перечислены все загруженные классы и, если я правильно помню, откуда они загружаются. См. http://docs.oracle.com/javase/7/docs/technotes/tools/windows/java.html для получения подробной информации.

person Jens Schauder    schedule 20.05.2014
comment
Привет, Дженс, я проверил, что API isAsyncStarted был добавлен в сервлет 3.0, и я использую java.servlet-3.0.jar в своей сборке проекта. - person Sourabh; 20.05.2014
comment
Это нормально для развития. Проверьте, использует ли сервер тот же уровень API сервлета. - person Manish Mudgal; 20.05.2014
comment
Сервер имеет тот же уровень API сервлета. - person Sourabh; 21.05.2014
comment
@Sourabh добавил некоторую информацию о том, как найти класс, вызывающий проблемы - person Jens Schauder; 21.05.2014
comment
Эй, Дженс, я смог найти HttpServletRequest. Это дает: Исключение в потоке main Метод) в java.net.URLClassLoader.findClass(URLClassLoader.java:190) в java.lang.ClassLoader.loadClass(ClassLoader.java:306) в sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) в java.lang.ClassLoader.loadClass(ClassLoader.java:247) - person Sourabh; 21.05.2014
comment
Я думаю, что по умолчанию в какой-то пакет включен javax.servlet, потому что даже когда я удалил пакет 3.0 из пути сборки, я все еще могу импортировать javax.servlet. Знаете ли вы, в каком пакете он находится, чтобы я мог обновить весь пакет. Кстати, я использую jdk 1.6 на случай, если это поможет - person Sourabh; 21.05.2014
comment
пакет будет такой же. Вопрос в том, что это за банка. Вот что вам покажет -verbose:class. - person Jens Schauder; 21.05.2014

Это происходит, когда ваша среда разработки и рабочая среда используют разные версии API сервлета.

При сборке с помощью tomcat7 (например) он поддерживает сервлет 3, поэтому вы не получите никаких ошибок.

Делая то же самое на более низкой версии tomcat, он выдает ошибку.

Решение:

Либо обновите одну из сред для поддержки сервлета 3, либо просто понизьте свой код, чтобы использовать сервлет 2.5.

person Manish Mudgal    schedule 20.05.2014
comment
Привет, Маниш, я думал о том же, но, как ни странно, я использовал apache tomcat 7.0.40 и javax.servlet-3.0.jar. Я не могу понизить сервлет javax до версии 2.5, так как он не содержит класса SessionCookieConfig. Таким образом, обновление Tomcat было бы вариантом, но оно уже в совместимой версии. - person Sourabh; 20.05.2014

Сообщение об ошибке указывает на то, что у вас неправильная версия Servlet API в пути к классам.

Если вы используете Gradle, выполните

gradle dependencies

проанализируйте дерево зависимостей и исключите зависимости «servlet-api» с версией ниже 3.0. Вы можете сделать следующее, чтобы исключить

compile ('javax.servlet:jsp-api:2.0'){
    exclude module : 'servlet-api'
}

Может быть несколько зависимостей, которые дополнительно включают servlet-api-2.x. Исключить все те

person Robin    schedule 16.02.2016
comment
Спасибо, это было решением в моем случае. org.apache:storm-core использует servlet-api 2.5, но io.confluent:kafka-schema-registry использует servlet-api 3.1. Мне пришлось исключить зависимость от storm, чтобы мой код заработал. - person asmaier; 11.11.2016

Я нашел решение своей ошибки. Фактический API-интерфейс сервлета, который был предоставлен, принадлежал gwt-servlet.jar, а API-интерфейс сервлета в gwt-servlet.jar был более старой версии. Таким образом, мне пришлось настроить свой путь сборки, чтобы проект указывал на последний servlet-api во время сборки.

Что касается правильного ответа, я думаю, что мой голос принадлежит Йенсу, поскольку он дал решение, наиболее близкое к сценарию.

Спасибо всем. :)

person Sourabh    schedule 23.05.2014
comment
Спасибо. Он работает с servlet-api.jar 3.0.1 без проблем. - person rakeeee; 21.06.2015

Я решаю эту проблему, добавляя tomcat в путь сборки java в качестве библиотеки времени выполнения сервера.

проблема mockito javax.servlet.SessionCookieConfig

person e2rabi    schedule 22.01.2017

У меня была аналогичная проблема, некоторые из моих тестов Junit не работали (в интеллектуальной идее), и я также получал 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. Проблема была решена.

person Waqar Detho    schedule 27.09.2017