web-dev-qa-db-ja.com

Spring Boot-コントローラのテストが404コードで失敗する

コントローラのテストを書きたいのですが。ここにテストスニペットがあります:

@RunWith(SpringRunner.class)
@WebMvcTest(WeatherStationController.class)
@ContextConfiguration(classes = MockConfig.class)
public class WeatherStationControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private IStationRepository stationRepository;

    @Test
    public void shouldReturnCorrectStation() throws Exception {

        mockMvc.perform(get("/stations")
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk());
    }
}

コントローラコードスニペット:

@RestController
@RequestMapping(value = "stations")
public class WeatherStationController {

    @Autowired
    private WeatherStationService weatherService;

    @RequestMapping(method = RequestMethod.GET)
    public List<WeatherStation> getAllWeatherStations() {
        return weatherService.getAllStations();
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public WeatherStation getWeatherStation(@PathVariable String id) {
        return weatherService.getStation(id);
    }

MockConfigクラス:

@Configuration
@ComponentScan(basePackages = "edu.lelyak.repository")
public class MockConfig {

    //**************************** MOCK BEANS ******************************

    @Bean
    @Primary
    public WeatherStationService weatherServiceMock() {
        WeatherStationService mock = Mockito.mock(WeatherStationService.class);
        return mock;
    }

ここにエラースタックトレースがあります:

Java.lang.AssertionError: Status 
Expected :200
Actual   :404

私はここで何が悪いのかを得ることができます。
コントローラーのテストを修正する方法?

10
nazar_art

HTTPコード404 は、リクエストに対して(サーバー上で)リソースが見つからないことを意味します。これは、コントローラーがスプリングブートで表示されない(スキャンされていない)と考えられます。

簡単な解決策は、MockConfigクラスの親パッケージをスキャンして、SpringがすべてのBeanを取得できるようにすることです。

_@ComponentScan(basePackages = "edu.lelyak") // assuming that's the parent package in your project
_

このアプローチが気に入らない場合は、コントローラのパッケージ名をbasePackagesに追加できます

_@ComponentScan(basePackages = {"edu.lelyak.controller","edu.lelyak.repository") 
_

ところで、WeatherStationServiceクラスでMockConfigを手動で設定する必要はありません。SpringBootはモックを挿入し、各テストメソッドの後に自動的にリセットできます。テストクラス:

_@MockBean
private IStationRepository stationRepository;
_

一方、テストメソッドでweatherService.getAllStations()を呼び出す前にget("/stations")をモックする必要があります( 統合テスト を実行していないため)。 :

_List<WeatherStation> myList = ...;
//Add element(s) to your list
 Mockito.when(stationService.getAllStations()).thenReturn(myList);
_

あなたはより多くを見つけることができます:

2
O.Badr

テストがうまくいかない理由はわかりません。しかし、私は私のために働く別の解決策を得ました。

@SpringBootTest
public class ControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.standaloneSetup(new TestController()).build();
    }

    @Test
    public void shouldReturnCorrectStation() throws Exception {
        mockMvc.perform(get("/stations")
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk());
    }
}
4
Patrick

ここで私のために働いたコントローラーテストへの異なるアプローチがあります。

仮定:クラスWeatherStationService@SpringBootApplication

次に、以下のテストクラスが機能するはずです。

@RunWith(SpringRunner.class)
@SpringApplicationConfiguration(WeatherStationService.class)
@WebIntegrationTest
public class WeatherStationControllerTest {

    @Autowired
    private WebApplicationContext context;

    MockMvc mockMvc;

    @Before
    public void setup() {
        mockMvc =  MockMvcBuilders.webAppContextSetup(this.context).build();
    }

    @Test
    public void shouldReturnCorrectStation() throws Exception {
        mockMvc.perform(get("/stations")
                .accept(MediaType.APPLICATION_JSON))
        .andExpect(status().isOk();
    }
}

このテストセットアップにより、MockConfigクラスは不要になります。

1
Nkokhelox

@ContextConfiguration(classes = MyConfig.class)で外部構成クラスをインポートします

MyConfigアノテーションを変更したとき@Configurationから@TestConfiguration正常に動作し始めました。

1
TOUDIdel

良い答えは見つかりませんでしたが、原因の1つを見つけることができました。

私はテストでRestControllerの@PreAuthorizeを使用していました。
SpringBootTestを使用する統合テストでOauth with this tip をモックすることができます。SpringBootTestの場合、これもうまく機能しますが、SpringBootTestを使用すると、単純なコントローラーテストを実行する必要のない他の多くのリソース(JPAなど)をロードします。

しかし@WebMvcTestでは、これは期待どおりに機能しません。 WithMockOAuth2Scope アノテーションを使用すれば、認証の問題による401エラーを回避できますが、その後、WebMvcTestは残りのエンドポイントを見つけることができず、404エラーコードを返します。

コントローラーの@PreAuthorizeを削除した後、WebMvcTestを使用したテストに合格します。

1
Dherik

私の場合、それは欠落している開始スラッシュについてでした/

最初の文字として/およびRequestMapping valueパラメータの両方にMockHttpServletRequestBuilder post urlTemplateを追加しました。

0
İsmail Yavuz