我为一些Spring MVC Controllers编写JUnit测试。JUnit测试的初始化对于所有控制器测试都是相同的,因此我想创建一个可以完成此初始化的抽象类。
因此,我创建了以下代码:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:spring/applicationContext-test.xml", "classpath*:spring/spring-mvc-test.xml" })
@Transactional
public abstract class AbstractSpringMVCControllerTest<T> {
@Autowired
protected ApplicationContext applicationContext;
protected MockHttpServletRequest request;
protected MockHttpServletResponse response;
protected HandlerAdapter handlerAdapter;
protected T controller;
@SuppressWarnings("unchecked")
@Before
public void initContext() throws SecurityException, NoSuchFieldException {
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
handlerAdapter = applicationContext.getBean(AnnotationMethodHandlerAdapter.class);
// Does not work, the problem is here...
controller = applicationContext.getBean(T);
}
}
我的想法是为我要测试的每个控制器创建一个扩展了我的 AbstractSpringMVCControllerTest
的JUnit测试类。在extends
声明中给定的类型是控制器的类。
例如,如果我想测试我的AccountController
,我将创建以下AccountControllerTest
类:
public class AccountControllerTest extends AbstractSpringMVCControllerTest<AccountController> {
@Test
public void list_accounts() throws Exception {
request.setRequestURI("/account/list.html");
ModelAndView mav = handlerAdapter.handle(request, response, controller);
...
}
}
我的问题出现在抽象类的
initContext()
方法的最后一行。这个抽象类声明了controller
对象作为一个T
对象,但是我该如何告诉Spring应用程序上下文返回类型为T
的bean呢?我尝试了类似于这样的代码:
Class<?> controllerClass = this.getClass().getSuperclass().getDeclaredField("controller").getType();
controller = (T) applicationContext.getBean(controllerClass);
但是controllerClass
返回的是java.lang.Object.class
类,而不是AccountController.class
。
当然,我可以创建一个public abstract Class<?> getControllerClass();
方法,每个JUnit控制器测试类都将重写该方法,但我更喜欢避免这种解决方案。
那么,你有什么想法吗?