TDDで足を濡らそうとしています。 MockMvcおよびJunitと組み合わせてMockitoを使用して、コントローラーの単体テストケースを作成しようとしています。
しかし、ランタイムエラーが発生し、テストに失敗します。最初は、_javax.servlet.SessionCookieConfig
_の検索に失敗したため、セットアップでMockMvcインスタンスを初期化する際に問題に直面していました。
これは、_javax.servlet
_ apiをダウンロードし、プロジェクトのビルドパスに構成することで解決しましたが、
_Java.lang.NoSuchMethodError: javax.servlet.http.HttpServletRequest.isAsyncStarted()
_
mockMvcインスタンスでperform()
を使用している間。
互換性のないサーバーservlet-apiとjavax.servletapiが原因で発生していると思うので、この種の依存関係をどうするか教えてもらえますか。
編集:私はユニットテストに使用しているコードを投稿していますが、念のためにそれが役に立たないと思います:
_@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;
}
}
_
これは、クラスパスに間違ったバージョンのサーブレットAPIがあるように聞こえます。
isAsyncStarted
がAPIにいつ追加されたかを確認し、クラスパスで参照しているものが少なくともそのバージョン以降であることを確認してください。
「間違った」クラスバージョンが発生している場所を見つけるには、
-verbose:class
Javaの引数。ロードされたすべてのクラスが一覧表示され、正しく覚えていれば、ロード元のクラスが表示されます。詳細については、 http://docs.Oracle.com/javase/7/docs/technotes/tools/windows/Java.html を参照してください。
これは、開発環境と本番環境で異なるサーブレットAPIバージョンを使用している場合に発生します。
たとえばTomcat7でビルドしている間は、サーブレット3をサポートしているため、エラーは発生しません。
下位バージョンのTomcatでも同じことを実行すると、エラーがスローされます。
解決策:
サーブレット3をサポートするように環境の1つをアップグレードするか、サーブレット2.5を使用するようにコードをダウングレードします。
エラーメッセージは、クラスパスにサーブレットAPIのバージョンが間違っていることを示しています。
Gradleを使用している場合は、実行
gradle dependencies
依存関係ツリーを分析し、バージョン3.0未満の「servlet-api」依存関係を除外します。除外するには、次の手順を実行できます
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 clean build
を使用してコマンドプロンプトでディレクトリからgradleを使用してプロジェクト全体をコンパイルしようとすると、コードは正常にコンパイルされていました。問題はIntellijアイデアのJUnitテストにありましたが、上記のエラーが表示されていました。 Gradleのバージョンを3.4.1から2.1.3に変更しただけです。 Junitテストがコンパイルされ、コードがintellijとコマンドプロンプトを介してコンパイルされている理由がわかりません。同じ問題が私の別の同僚でも発生し、彼もgradleバージョンを4から2のバージョンに変更しました。問題は解決しました。
エラーの解決策を見つけました。提供されていた実際のサーブレットAPIはgwt-servlet.jarであり、gwt-servlet.jarのサーブレットAPIは古いバージョンでした。したがって、ビルド中にプロジェクトが最新のサーブレットAPIを指すようにビルドパスを構成しました。
正解については、シナリオ通りに最も近い解決策を彼が与えたので、私の投票はイェンスに行くと思います。
みんな、ありがとう。 :)