簡體   English   中英

Spring 開機測試濾波器

[英]Spring Boot test Filter

注意:下面的錯誤實際上是由過濾器中的拼寫錯誤引起的,請參閱@jccampanero 在下面的回答中提到

我一直在嘗試幾種不同的方法來測試過濾器,但是我不斷收到一個或另一個錯誤,所以我希望有一些方向。

這是一個應該只進行重定向的虛擬過濾器。


package org.example.filters;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class RedirectFilter implements Filter {
  @Override
  public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
      throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) req;
    chain.sendRedirect("/splash");
  }
}

還有一個基本的 Spring 引導應用程序 class:

package org.example;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ApplicationClass {

}

我想我只是不清楚我正在嘗試做的 Spring 引導測試的“級別”是什么,這是我做過的一些嘗試和錯誤:

選項 1. 嘗試使用模擬,例如從這里

package org.example.filters;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;
import org.junit.jupiter.api.Test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

public class LocaleFilterIntegrationTestStandalone {

  @Test
  public void whenNoLocaleRedirectToSplash() throws Exception {
    standaloneSetup(new TestController()).addFilters(new RedirectFilter()).build().perform(get("/"))
        .andExpect(status().isFound()).andExpect(redirectedUrl("/splash"));
  }

  @Controller
  private static class TestController {
    @GetMapping("/")
    public String get() {
      return "got it";
    }
  }
}

Error: java.lang.ClassCastException: class org.springframework.mock.web.MockHttpServletRequest cannot be cast to class javax.servlet.http.HttpServletResponse

選項 2,嘗試使用@WebMvcTest ,它與選項 1 有相同的問題

package org.example.filters;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.stereotype.Controller;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.bind.annotation.GetMapping;

@WebMvcTest
public class LocaleFilterIntegrationTestWebMvc {
  @Autowired
  private MockMvc mvc;

  @Test
  public void noLanguageShouldRedirectToSplash() throws Exception {
    mvc.perform(get("/")).andExpect(status().isFound()).andExpect(redirectedUrl("/splash"));
  }

  @Controller
  private static class TestController {
    @GetMapping("/")
    public String get() {
      return "got it";
    }
  }
}

Error: java.lang.ClassCastException: class org.springframework.mock.web.MockHttpServletRequest cannot be cast to class javax.servlet.http.HttpServletResponse

選項 3,嘗試啟動整個上下文,我認為這是能夠轉換為HttpServletRequest所必需的:

package org.example.filters;

import java.net.URI;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class LocaleFilterIntegrationTest {
  @LocalServerPort
  private int port;

  @Autowired
  private TestRestTemplate restTemplate;

  @Test
  public void noLanguageShouldRedirectToSplash() throws Exception {
    URI uri = new URI("http", "localhost:" + port, "/", null, null);
    String result = restTemplate.getForObject(uri.toString(), String.class);
    // not sure how, but test for redirect...
  }

  @Controller
  private static class TestController {
    @GetMapping("/")
    public String get() {
      return "got it";
    }
  }
}

Error: class org.apache.catalina.connector.RequestFacade cannot be cast to class javax.servlet.http.HttpServletResponse

@m-deinem 建議的選項 4

package org.example.filters;

import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;

public class LocaleFilterIntegrationTestPlain {
  private final RedirectFilter redirectFilter = new RedirectFilter();

  @Test
  public void noLanguageShouldRedirectToSplash() throws Exception {
    MockHttpServletRequest req = new MockHttpServletRequest();
    MockHttpServletResponse res = new MockHttpServletResponse();
    MockFilterChain chain = new MockFilterChain();
    redirectFilter.doFilter(req, res, chain);
  }
}

Error: java.lang.ClassCastException: class org.springframework.mock.web.MockHttpServletRequest cannot be cast to class javax.servlet.http.HttpServletResponse

首先,您的RedirectFilter包含一個錯誤,它嘗試將傳入的HttpServletRequest轉換為HttpServletResponse ,因為您使用了錯誤的變量。

@Component
public class RedirectFilter implements Filter {
  @Override
  public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
      throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;
    res.sendRedirect("/splash");
  }
}

這兩行都使用req而后者應該使用res (這也是異常字面上告訴你的)。

接下來只需編寫一個簡單的單元測試,通過嘗試編寫集成測試使事情變得過於復雜。

public class RedirectFilterTest

  private final RedirectFilter filter = new RedirectFilter();

  @Test
  public void redirectTest() {
    MockHttpServletRequest req = new MockHttpServletRequest();
    MockHttpServletResponse res = new MockHttpServletResponse();
    MockFilterChain chain = new MockFilterChain();
 
    filter.doFilter(req, res, chain);

    assertEquals("/splash", res.getRedirectedUrl());
  }

請,也許這只是一個錯字,但請注意,在您的RedirectFilter doFilter方法中,您錯誤地將變量req轉換為HttpServletResponse

package org.example.filters;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class RedirectFilter implements Filter {
  @Override
  public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
      throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) req;
    // Please, note the incorrect cast
    HttpServletResponse response = (HttpServletResponse) req;
    chain.sendRedirect("/splash");
  }
}

相反,它應該是:

package org.example.filters;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class RedirectFilter implements Filter {
  @Override
  public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
      throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;
    chain.sendRedirect("/splash");
  }
}

這很可能是ClassCastException和測試失敗的原因。

解決后,@M 提出的解決方案。 Deinum 是一個非常好的和直接的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM