كيفية اختبار وحدة وحدة تحكم الربيع MVC باستخدامPathVariable؟

StackOverflow https://stackoverflow.com/questions/1401128

سؤال

ولدي وحدة تحكم بسيطة المشروح مشابهة لهذه واحدة:

@Controller
public class MyController {
  @RequestMapping("/{id}.html")
  public String doSomething(@PathVariable String id, Model model) {
    // do something
    return "view";
  }
}

ووأريد أن اختبار مع اختبار وحدة من هذا القبيل:

public class MyControllerTest {
  @Test
  public void test() {
    MockHttpServletRequest request = new MockHttpServletRequest();
    request.setRequestURI("/test.html");
    new AnnotationMethodHandlerAdapter()
      .handle(request, new MockHttpServletResponse(), new MyController());
    // assert something
  }
}

والمشكلة هي أن AnnotationMethodHandlerAdapter.handler () طريقة رميات استثناء:

java.lang.IllegalStateException: Could not find @PathVariable [id] in @RequestMapping
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.resolvePathVariable(AnnotationMethodHandlerAdapter.java:642)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolvePathVariable(HandlerMethodInvoker.java:514)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:262)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:146)
هل كانت مفيدة؟

المحلول

واعتبارا من الربيع 3.2، هناك وسيلة مناسبة لاختبار هذا، بطريقة أنيقة وسهلة. سوف تكون قادرا على القيام باشياء مثل هذا:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration("servlet-context.xml")
public class SampleTests {

  @Autowired
  private WebApplicationContext wac;

  private MockMvc mockMvc;

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

  @Test
  public void getFoo() throws Exception {
    this.mockMvc.perform(get("/foo").accept("application/json"))
        .andExpect(status().isOk())
        .andExpect(content().mimeType("application/json"))
        .andExpect(jsonPath("$.name").value("Lee"));
  }
}

لمزيد من المعلومات، نلقي نظرة على الموقع http://blog.springsource.org/2012/11/12/spring-framework-3-2-rc1-spring-mvc-test-framework/

نصائح أخرى

وأسميه ما كنت بعد تجربة التكامل على أساس المصطلحات في الدليل المرجعي الربيع. ماذا عن فعل شيء من هذا القبيل:

import static org.springframework.test.web.ModelAndViewAssert.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({/* include live config here
    e.g. "file:web/WEB-INF/application-context.xml",
    "file:web/WEB-INF/dispatcher-servlet.xml" */})
public class MyControllerIntegrationTest {

    @Inject
    private ApplicationContext applicationContext;

    private MockHttpServletRequest request;
    private MockHttpServletResponse response;
    private HandlerAdapter handlerAdapter;
    private MyController controller;

    @Before
    public void setUp() {
       request = new MockHttpServletRequest();
       response = new MockHttpServletResponse();
       handlerAdapter = applicationContext.getBean(HandlerAdapter.class);
       // I could get the controller from the context here
       controller = new MyController();
    }

    @Test
    public void testDoSomething() throws Exception {
       request.setRequestURI("/test.html");
       final ModelAndView mav = handlerAdapter.handle(request, response, 
           controller);
       assertViewName(mav, "view");
       // assert something
    }
}

لمزيد من المعلومات لقد كتبت <لأ href = "http://www.scarba05.co.uk/blog/2010/03/integration-testing-of-springs-mvc-annotation-mapppings-for- التحكم / "يختلط =" noreferrer "> دخول بلوق عن التكامل اختبار الشروح الربيع MVC .

وإطار واعد لاختبار الربيع MVC https://github.com/SpringSource/spring-test-mvc

وتشير رسالة الاستثناء إلى "تغذية" متغير، وهي ليست موجودة في نموذج التعليمات البرمجية الخاصة بك، من المحتمل أن يكون سببه شيئا لم تكن قد أظهرت لنا.

وأيضا، الاختبار هو اختبار الربيع <م> و التعليمات البرمجية الخاصة بك. هل هذا حقا ما كنت تريد أن تفعل؟

ومن الأفضل أن نفترض أن يعمل الربيع (وهو ما يحدث بالفعل)، ومجرد اختبار الفئة الخاصة بك، أي دعوة MyController.doSomething() مباشرة. هذا هو فائدة واحدة من نهج الشرح - لا تحتاج إلى استخدام طلبات وهمية والاستجابات، عليك فقط استخدام POJOs المجال

شريطة أن تستخدم 3.0.x الربيع.

وهنا أقترح دمج اميل والأجوبة scarba05 باستخدام الربيع اختبار لا ربيع للتجارب MVC. الرجاء تخطي هذه الإجابة والإشارة إلى أمثلة الربيع اختبار MVC إذا كنت تستخدم 3.2.x الربيع أو في وقت لاحق

MyControllerWithParameter.java

@Controller
public class MyControllerWithParameter {
@RequestMapping("/testUrl/{pathVar}/some.html")
public String passOnePathVar(@PathVariable String pathVar, ModelMap model){
    model.addAttribute("SomeModelAttribute",pathVar);
    return "viewName";
}
}

MyControllerTest.java

import static org.springframework.test.web.ModelAndViewAssert.assertViewName;
import java.util.HashMap;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.ModelAndViewAssert;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = 
    {"file:src\\main\\webapp\\WEB-INF\\spring\\services\\servlet-context.xml" 
    })
public class MyControllerTest {

private MockHttpServletRequest request;
private MockHttpServletResponse response;
private HandlerAdapter handlerAdapter;

@Before
public void setUp() throws Exception {
    request = new MockHttpServletRequest();
    response = new MockHttpServletResponse();
    this.handlerAdapter = applicationContext.getBean(AnnotationMethodHandlerAdapter.class);
}

//  Container beans
private MyControllerWithParameter myController;
private ApplicationContext applicationContext;
public ApplicationContext getApplicationContext() {
    return applicationContext;
}
@Autowired
public void setApplicationContext(ApplicationContext applicationContext) {
    this.applicationContext = applicationContext;
}
public MyControllerWithParameter getMyController() {
    return myController;
}
@Autowired
public void setMyController(MyControllerWithParameter myController) {
    this.myController = myController;
}

@Test
public void test() throws Exception {
    request.setRequestURI("/testUrl/Irrelavant_Value/some.html");
    HashMap<String, String> pathvars = new HashMap<String, String>();
    // Populate the pathVariable-value pair in a local map
    pathvars.put("pathVar", "Path_Var_Value");
    // Assign the local map to the request attribute concerned with the handler mapping 
    request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, pathvars);

    final ModelAndView modelAndView = this.handlerAdapter.handle(request, response, myController);

    ModelAndViewAssert.assertAndReturnModelAttributeOfType(modelAndView, "SomeModelAttribute", String.class);
    ModelAndViewAssert.assertModelAttributeValue(modelAndView, "SomeModelAttribute", "Path_Var_Value");
    ModelAndViewAssert.assertViewName(modelAndView, "viewName");
}

و}

ولقد وجدت أن يمكنك إدراج رسم الخرائط PathVariable في وجوه الطلب يدويا. هذا هو واضح غير مثالية ولكن يبدو أن العمل. في المثال الخاص بك، شيئا مثل:

@Test
public void test() {
    MockHttpServletRequest request = new MockHttpServletRequest();
    request.setRequestURI("/test.html");
    HashMap<String, String> pathvars = new HashMap<String, String>();
    pathvars.put("id", "test");
    request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, pathvars);
    new AnnotationMethodHandlerAdapter().handle(request, new MockHttpServletResponse(), new MyController());
   // assert something
}

وسأكون بالتأكيد ترغب في العثور على أفضل خيار.

ولست متأكدا جوابي الأصلي هو الذهاب للمساعدة فيPathVariable. لقد حاولت مجرد اختبار لPathVariable وأحصل على استثناء التالية:

وorg.springframework.web.bind.annotation.support.HandlerMethodInvocationException: فشل استدعاء أسلوب معالج [الجمهور org.springframework.web.servlet.ModelAndView test.MyClass.myMethod (test.SomeType)]. استثناء متداخلة هو java.lang.IllegalStateException: تعذر العثور علىPathVariable [parameterName التي] فيRequestMapping

والسبب هو أن المتغيرات المسار في طلب الحصول على تحليل من قبل اعتراضية. النهج التالي يعمل بالنسبة لي:

import static org.springframework.test.web.ModelAndViewAssert.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"file:web/WEB-INF/application-context.xml",
        "file:web/WEB-INF/dispatcher-servlet.xml"})    
public class MyControllerIntegrationTest {

    @Inject
    private ApplicationContext applicationContext;

    private MockHttpServletRequest request;
    private MockHttpServletResponse response;
    private HandlerAdapter handlerAdapter;

    @Before
    public void setUp() throws Exception {
        this.request = new MockHttpServletRequest();
        this.response = new MockHttpServletResponse();

        this.handlerAdapter = applicationContext.getBean(HandlerAdapter.class);
    }

    ModelAndView handle(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        final HandlerMapping handlerMapping = applicationContext.getBean(HandlerMapping.class);
        final HandlerExecutionChain handler = handlerMapping.getHandler(request);
        assertNotNull("No handler found for request, check you request mapping", handler);

        final Object controller = handler.getHandler();
        // if you want to override any injected attributes do it here

        final HandlerInterceptor[] interceptors =
            handlerMapping.getHandler(request).getInterceptors();
        for (HandlerInterceptor interceptor : interceptors) {
            final boolean carryOn = interceptor.preHandle(request, response, controller);
            if (!carryOn) {
                return null;
            }
        }

        final ModelAndView mav = handlerAdapter.handle(request, response, controller);
        return mav;
    }

    @Test
    public void testDoSomething() throws Exception {
        request.setRequestURI("/test.html");
        request.setMethod("GET");
        final ModelAndView mav = handle(request, response);
        assertViewName(mav, "view");
        // assert something else
    }

ولقد إضافة بلوق وظيفة جديدة على <لأ href = "http://www.scarba05.co.uk/blog/2010/07/more-on-integration-testing-of-spring٪E2٪80 ٪ 99S-MVC-الشرح-mapppings مقابل وحدات التحكم / "يختلط =" نوفولو noreferrer "> التكامل اختبار الربيع الشروح MVC

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top