Closed8
SpringBoot + JUnitでREST APIのテストをする
NullPointerになる
java.lang.NullPointerException
at captain.blue210.studyfornetsuperbackend.presentation.api.controller.goods.GoodsControllerTest.testGetAllItems(GoodsControllerTest.java:27)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
<省略>
Controllerのテストにはテストクラスに@SpringBootTestアノテーションが必要
つけて実行すると、エラー内容が変わった
2021-01-17 21:02:38.579 ERROR 38167 --- [ main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@6da21078] to prepare test instance [captain.blue210.studyfornetsuperbackend.presentation.api.controller.goods.GoodsControllerTest@72725ee1]
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'captain.blue210.studyfornetsuperbackend.presentation.api.controller.goods.GoodsControllerTest': Unsatisfied dependency expressed through field 'mock'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.test.web.servlet.MockMvc' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643) ~[spring-beans-5.3.2.jar:5.3.2]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.2.jar:5.3.2]
<省略>
NoSuchBeanDefinitionExceptionというものがでているらしい。
これを調べると、@Componentのつけ忘れに気づく。
つけて再度実行したがまだ実行に失敗する
テストクラスのアノテーション指定が不足していたっぽい。
以下を付与したらテスト自体はできた
GoodsControllerTest.java
@SpringBootTest
@AutoConfigureMockMvc
public GoodsControllerClass {
...
}
もしくは、
GoodsControllerTest.java
@WebMvcTest
class GoodsControllerTest {
...
}
テスト自体は実行されるが、MockMvcでのリクエストが401になっている
MockHttpServletRequest:
HTTP Method = GET
Request URI = /api/items
Parameters = {}
Headers = []
Body = null
Session Attrs = {SPRING_SECURITY_SAVED_REQUEST=DefaultSavedRequest [http://localhost/api/items]}
Handler:
Type = null
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 401
Error message = Unauthorized
Headers = [WWW-Authenticate:"Basic realm="Realm"", X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
@WithMockUserを使うと、ステータスは200になった。
SecurityConfigの設定すれば、上記は不要?
Spring Securityはデフォルトだとログインページ以外、アクセスに認証が必要な設定になっている
【Spring Security はじめました 】#1 導入
実際に画面からアクセスしてみるとログイン画面に戻される

xxxApplication.java(mainクラスがあるやつ)と同じ階層にWebSecurityConfigurerAdapterを継承したクラスを作成し、認証なしでアクセスできるページを設定する。
※import文省略
WebSecurityConfig.java
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/api/items").permitAll().anyRequest().authenticated();
}
}
これでテストを走らせると無事200でステータスが返ってくる
このスクラップは2021/01/18にクローズされました