2015-01-10 6 views
1

Я пытаюсь выполнить приведенные выше примеры в Spring in Action (4th edition), глава 5, чтобы создать собственный проект. (Все еще новичок на уровне предприятия) Я использую ПК с Windows 7, Java 7, Spring 4 и Maven. Когда я запускаю свой ClinicalNoteControllerTest, тест не выполняется с ошибкой NoSuchMethod на определенной строке. Но я исследовал эту линию, и, похоже, она написана правильно. Это определенно следует примеру в книге. Я отлаживал, но ничего не могу найти в том, что там появляется. Мне интересно, если у меня нет правильной конфигурации в моем файле pom.xml?Ошибка NoSuchMethod при запуске теста Spring MVC

Вы, ребята, всегда так полезны, и я буду признателен за любую помощь, которую вы можете дать найти решение здесь. Но я также хочу стать лучшим инструментом устранения неполадок, а не просто запускать stackoverflow каждый раз, когда я нажимаю удар. Поэтому любые советы, которые вы можете дать о том, как я могу самостоятельно устранить эту проблему, будут очень благодарны.

Вот тест:

package com.kwalker.practicewellness; 

import java.util.ArrayList; 
import java.util.Date; 
import java.util.List; 

import org.junit.Test; 

import static org.mockito.Mockito.*; 

import org.springframework.test.web.servlet.MockMvc; 

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; 
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; 
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*; 
import static org.hamcrest.Matchers.*; 

import org.springframework.web.servlet.view.InternalResourceView; 

import com.kwalker.practicewellness.data.ClinicalNoteRepository; 
import com.kwalker.practicewellness.domain.ClinicalNote; 
import com.kwalker.practicewellness.web.ClinicalNoteController; 

public class ClinicalNoteControllerTest { 

@Test 
public void shouldShowRecentClinicalNotes() throws Exception { 
    List<ClinicalNote> expectedClinicalNotes = createClinicalNoteList(20); 
    ClinicalNoteRepository mockNoteRepository = mock(ClinicalNoteRepository.class); 
    when(mockNoteRepository.findClinicalNotes(Long.MAX_VALUE, 20)).thenReturn(expectedClinicalNotes); 

    ClinicalNoteController noteController = new ClinicalNoteController(mockNoteRepository); 
    MockMvc mockMvc = standaloneSetup(noteController).setSingleView(
      new InternalResourceView("/WEB-INF/views/clinicalNotes.jsp")).build(); 

    mockMvc.perform(get("/clinical-notes")) 
     .andExpect(view().name("clinicalNotes")) 
     .andExpect(model().attributeExists("clinicalNoteList")) 
     .andExpect(model().attribute("clinicalNoteList", hasItems(expectedClinicalNotes.toArray()))); 
} 

private List<ClinicalNote> createClinicalNoteList(int count) { 
    List<ClinicalNote> clinicalNotes = new ArrayList<ClinicalNote>(); 
    for (int i=0; i < count; i++) { 
     clinicalNotes.add(new ClinicalNote("Note " + i, new Date())); 
    } 
    return clinicalNotes; 
} 

} 

Вот это ClinicalNoteController:

package com.kwalker.practicewellness.web; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Controller; 
import org.springframework.ui.Model; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 

import com.kwalker.practicewellness.data.ClinicalNoteRepository; 

@Controller 
@RequestMapping("/clinical-notes") 
public class ClinicalNoteController { 

private ClinicalNoteRepository noteRepository; 

@Autowired 
public ClinicalNoteController(ClinicalNoteRepository noteRepository) { 
    this.noteRepository = noteRepository; 
} 

@RequestMapping(method=RequestMethod.GET) 
public String clinicalNotes(Model model) { 
    model.addAttribute("clinicalNoteList", noteRepository.findClinicalNotes(Long.MAX_VALUE, 20)); 
    return "clinicalNotes"; 
} 

} 

Вот что выводит на консоль при запуске теста:

INFO : org.springframework.test.web.servlet.setup.StandaloneMockMvcBuilder$StaticRequestMappingHandlerMapping - Mapped "{[/clinical-notes],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String com.kwalker.practicewellness.web.ClinicalNoteController.clinicalNotes(org.springframework.ui.Model) 
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter - Looking for @ControllerAdvice: org.s[email protected]41494678 
INFO : org.springframework.mock.web.MockServletContext - Initializing Spring FrameworkServlet '' 
INFO : org.springframework.test.web.servlet.TestDispatcherServlet - FrameworkServlet '': initialization started 
INFO : org.springframework.test.web.servlet.TestDispatcherServlet - FrameworkServlet '': initialization completed in 16 ms 

Здесь является следствием отказа:

java.lang.NoSuchMethodError: org.hamcrest.Matcher.describeMismatch(Ljava/lang/Object;Lorg/hamcrest/Description;)V 
at org.hamcrest.core.IsCollectionContaining.matchesSafely(IsCollectionContaining.java:31) 
at org.hamcrest.core.IsCollectionContaining.matchesSafely(IsCollectionContaining.java:14) 
at org.hamcrest.TypeSafeDiagnosingMatcher.matches(TypeSafeDiagnosingMatcher.java:55) 
at org.hamcrest.core.AllOf.matches(AllOf.java:24) 
at org.springframework.test.util.MatcherAssertionErrors.assertThat(MatcherAssertionErrors.java:65) 
at org.springframework.test.web.servlet.result.ModelResultMatchers$1.match(ModelResultMatchers.java:56) 
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:152) 
at com.kwalker.practicewellness.ClinicalNoteControllerTest.shouldShowRecentClinicalNotes(ClinicalNoteControllerTest.java:39) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:606) 
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) 
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) 
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76) 
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) 
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) 
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) 
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) 
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) 
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) 
at org.junit.runners.ParentRunner.run(ParentRunner.java:236) 
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192) 

Вот мой POM файл:

<?xml version="1.0" encoding="UTF-8"?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 
<modelVersion>4.0.0</modelVersion> 

<groupId>com.kwalker</groupId> 
<artifactId>practicewellness</artifactId> 
<name>Practice Wellness</name> 
<packaging>war</packaging> 
<version>1.0.0-BUILD-SNAPSHOT</version> 

<properties> 
    <java-version>1.7</java-version> 
    <org.springframework-version>4.1.4.RELEASE</org.springframework-version> 
    <org.aspectj-version>1.6.10</org.aspectj-version> 
    <org.slf4j-version>1.6.6</org.slf4j-version> 

</properties> 

<dependencies> 
    <!-- Spring --> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-context</artifactId> 
     <version>${org.springframework-version}</version> 
     <exclusions> 
      <!-- Exclude Commons Logging in favor of SLF4j --> 
      <exclusion> 
       <groupId>commons-logging</groupId> 
       <artifactId>commons-logging</artifactId> 
      </exclusion> 
     </exclusions> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-webmvc</artifactId> 
     <version>${org.springframework-version}</version> 
    </dependency> 

    <!-- AspectJ --> 
    <dependency> 
     <groupId>org.aspectj</groupId> 
     <artifactId>aspectjrt</artifactId> 
     <version>${org.aspectj-version}</version> 
    </dependency> 

    <!-- Logging --> 
    <dependency> 
     <groupId>org.slf4j</groupId> 
     <artifactId>slf4j-api</artifactId> 
     <version>${org.slf4j-version}</version> 
    </dependency> 
    <dependency> 
     <groupId>org.slf4j</groupId> 
     <artifactId>jcl-over-slf4j</artifactId> 
     <version>${org.slf4j-version}</version> 
     <scope>runtime</scope> 
    </dependency> 
    <dependency> 
     <groupId>org.slf4j</groupId> 
     <artifactId>slf4j-log4j12</artifactId> 
     <version>${org.slf4j-version}</version> 
     <scope>runtime</scope> 
    </dependency> 
    <dependency> 
     <groupId>log4j</groupId> 
     <artifactId>log4j</artifactId> 
     <version>1.2.15</version> 
     <exclusions> 
      <exclusion> 
       <groupId>javax.mail</groupId> 
       <artifactId>mail</artifactId> 
      </exclusion> 
      <exclusion> 
       <groupId>javax.jms</groupId> 
       <artifactId>jms</artifactId> 
      </exclusion> 
      <exclusion> 
       <groupId>com.sun.jdmk</groupId> 
       <artifactId>jmxtools</artifactId> 
      </exclusion> 
      <exclusion> 
       <groupId>com.sun.jmx</groupId> 
       <artifactId>jmxri</artifactId> 
      </exclusion> 
     </exclusions> 
     <scope>runtime</scope> 
    </dependency> 

    <!-- @Inject --> 
    <dependency> 
     <groupId>javax.inject</groupId> 
     <artifactId>javax.inject</artifactId> 
     <version>1</version> 
    </dependency> 

    <!-- Servlet --> 
    <dependency> 
     <groupId>javax.servlet</groupId> 
     <artifactId>javax.servlet-api</artifactId> 
     <version>3.1.0</version> 
     <scope>provided</scope> 
    </dependency> 
    <dependency> 
     <groupId>javax.servlet.jsp</groupId> 
     <artifactId>jsp-api</artifactId> 
     <version>2.2</version> 
     <scope>provided</scope> 
    </dependency> 
    <dependency> 
     <groupId>javax.servlet</groupId> 
     <artifactId>jstl</artifactId> 
     <version>1.2</version> 
    </dependency> 

    <!-- Test --> 
    <dependency> 
     <groupId>junit</groupId> 
     <artifactId>junit</artifactId> 
     <version>4.7</version> 
     <scope>test</scope> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-test</artifactId> 
     <version>4.1.4.RELEASE</version> 
    </dependency> 
    <dependency> 
     <groupId>org.mockito</groupId> 
     <artifactId>mockito-all</artifactId> 
     <version>1.10.19</version> 
    </dependency> 
    <dependency> 
     <groupId>org.hamcrest</groupId> 
     <artifactId>hamcrest-library</artifactId> 
     <version>1.3</version> 
    </dependency> 

    <!-- Misc --> 
    <dependency> 
     <groupId>org.apache.commons</groupId> 
     <artifactId>commons-lang3</artifactId> 
     <version>3.3.2</version> 
    </dependency> 

</dependencies> 
<build> 
    <plugins> 
     <plugin> 
      <artifactId>maven-eclipse-plugin</artifactId> 
      <version>2.9</version> 
      <configuration> 
       <additionalProjectnatures> 
        <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature> 
       </additionalProjectnatures> 
       <additionalBuildcommands> 
        <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand> 
       </additionalBuildcommands> 
       <downloadSources>true</downloadSources> 
       <downloadJavadocs>true</downloadJavadocs> 
      </configuration> 
     </plugin> 
     <plugin> 
      <groupId>org.apache.maven.plugins</groupId> 
      <artifactId>maven-compiler-plugin</artifactId> 
      <version>3.2</version> 
      <configuration> 
       <source>1.7</source> 
       <target>1.7</target> 
       <compilerArgument>-Xlint:all</compilerArgument> 
       <showWarnings>true</showWarnings> 
       <showDeprecation>true</showDeprecation> 
      </configuration> 
     </plugin> 
     <plugin> 
      <groupId>org.codehaus.mojo</groupId> 
      <artifactId>exec-maven-plugin</artifactId> 
      <version>1.3.1</version> 
      <configuration> 
       <mainClass>org.test.int1.Main</mainClass> 
      </configuration> 
     </plugin> 
    </plugins> 
</build> 

Вот мой WebApp инициализатор:

package com.kwalker.practicewellness.config; 

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; 

public class WellnessWebAppInitializer extends 
    AbstractAnnotationConfigDispatcherServletInitializer { 

@Override 
protected Class<?>[] getRootConfigClasses() { 
    return new Class<?>[] { RootConfig.class }; 
} 

@Override 
protected Class<?>[] getServletConfigClasses() { 
    return new Class<?>[] { WebConfig.class }; 
} 

@Override 
protected String[] getServletMappings() { 
    return new String[] { "/" }; 
} 

} 

Вот мой WebConfig файл:

package com.kwalker.practicewellness.config; 

import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.ComponentScan; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.web.servlet.ViewResolver; 
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; 
import org.springframework.web.servlet.config.annotation.EnableWebMvc; 
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 
import org.springframework.web.servlet.view.InternalResourceViewResolver; 

@Configuration 
@EnableWebMvc 
@ComponentScan("com.kwalker.practicewellness.web") 
public class WebConfig extends WebMvcConfigurerAdapter { 

@Bean 
public ViewResolver viewResolver() { 
    InternalResourceViewResolver resolver = new InternalResourceViewResolver(); 
    resolver.setPrefix("/WEB-INF/views/"); 
    resolver.setSuffix(".jsp"); 
    resolver.setExposeContextBeansAsAttributes(true); 
    return resolver; 
} 

@Override 
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { 
    configurer.enable(); 
} 

} 

Вот класс RootConfig:

package com.kwalker.practicewellness.config; 

import org.springframework.context.annotation.ComponentScan; 
import org.springframework.context.annotation.ComponentScan.Filter; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.context.annotation.FilterType; 
import org.springframework.web.servlet.config.annotation.EnableWebMvc; 

@Configuration 
@ComponentScan(basePackages={"com.kwalker.practicewellness"}, 
      excludeFilters={@Filter(type=FilterType.ANNOTATION, value=EnableWebMvc.class)}) 
public class RootConfig { 

} 
+2

Эта ошибка почти всегда указывает на то, что у вас есть неправильная версия либо библиотеки с методом недостающей или библиотеки, которая делает несуществующего вызова метода. – chrylis

+0

Вот что я думал, что проблема была где-то в файле POM. Ваш комментарий поставил меня на новый поиск, и я наткнулся на эту страницу, в которой была рассмотрена эта точная проблема: http://tedvinke.wordpress.com/2013/12/17/mixing-junit-hamcrest-and-mockito-explaining-nosuchmethoderror/ –

+0

Здесь может быть полезно представление иерархии зависимостей Eclipse, так как оно показывает дерево зависимостей вместе с тем, как были рассчитаны разрешенные версии для каждого пакета. – chrylis

ответ

3

Это точная проблема решается на блоге Ted Vinke с декабря 2013 года: Mixing JUnit, Hamcrest and Mockito

Я использовал код, приведенный на этой странице, чтобы изменить мой POM файл (который в основном участвует переставляя Mockito, JUnit и Hamcrest, и исключая hamcrest на зависимость mockito). ВАЖНО ПРИМЕЧАНИЕ. Я использовал последние версии этих ресурсов, а исправление DID NOT WORK, пока я не установил версии в моем файле POM, не соответствует версиям, указанным на странице по этой ссылке. Вот текст из ссылки:

Это может быть связано с тем, что сам JUnit приносит свою версию Hamcrest в качестве транзитивной зависимости. Теперь, если вы будете использовать JUnit 4.11, это будет в зависимости от Hamcrest 1.3 уже. Превышение ошибки будет странным - поскольку метод описанияMismatch присутствует в интерфейсе org.hamcrest.Matcher. Кажется, есть более старая версия org.hamcrest.Matcher, присутствующая на пути к классам, которому принадлежит org.junit.Assert.assertThat делегаты. Если вы запустите это из Eclipse или IntelliJ, существует высокая вероятность того, что среда IDE использует собственную версию JUnit вместо вашей зависимости от Maven ...

Статья продолжает:

Если мы ищем в Eclipse, для сличитель классов мы например мог видеть, что есть и один в mockito-all-1.9.5.jar .... Кажется, mockito - все несовместимо с JUnit 4.11 для соображений обратной совместимости. Hamcherest версии 1.1 Matcher был упакован в зависимости, поэтому мы не можем его исключить .... К счастью для нас, Mockito позволяет нам использовать зависимость от mockito-core вместо mockito-all. Выполнение проверки зависимостей (с зависимостью: дерево или онлайн) показывает, что это зависит от hamcrest-core ..... Мы можем исключить его в pom.xml и - не более NoSuchMethodError. Вот окончательное сочетание зависимостей в нашем случае:

<dependency> 
    <groupId>org.mockito</groupId> 
    <artifactId>mockito-core</artifactId> 
    <version>1.9.5</version> 
    <exclusions> 
     <exclusion> 
      <artifactId>hamcrest-core</artifactId> 
      <groupId>org.hamcrest</groupId> 
     </exclusion> 
    </exclusions> 
</dependency> 
<dependency> 
    <groupId>junit</groupId> 
    <artifactId>junit</artifactId> 
    <version>4.11</version> 
    <exclusions> 
     <exclusion> 
      <artifactId>hamcrest-core</artifactId> 
      <groupId>org.hamcrest</groupId> 
     </exclusion> 
    </exclusions> 
</dependency> 
<dependency> 
    <groupId>org.hamcrest</groupId> 
    <artifactId>hamcrest-all</artifactId> 
    <version>1.3</version> 
</dependency> 
+1

Отлично, что вы нашли свое решение, но, пожалуйста, добавьте конкретные тексты, связанные с вашей проблемой, в ответ на эту ссылку. Таким образом, если эта ссылка сломается, ваш ответ по-прежнему будет полезен другим. +1 в любом случае для усилий! :) –

+1

Спасибо, Хорхе. Я отредактировал вышеупомянутый раздел, чтобы включить текст и код с веб-сайта, где я нашел решение. –

Смежные вопросы