我为一些 Spring MVC Controller 编写 JUnit 测试。 JUnit 测试的初始化对于我所有的 Controller 测试都是通用的,因此我想创建一个抽象类来执行此初始化。
因此,我创建了以下代码:
@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);
}
}
我的想法是为每个我想测试的 Controller 创建一个扩展我的 AbstractSpringMVCControllerTest
的 JUnit 测试类。 . extends
中给出的类型声明是 Controller 的类。
例如,如果我想测试我的 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 Application Context 返回类型为 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 Controller 测试类覆盖,但我更愿意避免这种解决方案。
那么,有什么想法吗?
最佳答案
如果 AbstractSpringMVCControllerTest
的子类在编译时绑定(bind) T
,这是可能的。也就是说,你有类似的东西
public class DerpControllerTest extends AbstractSpringMVCControllerTest<DerpController> { }
而不是
public class AnyControllerTest<T> extends AbstractSpringMVCControllerTest<T> { }
我猜你可能有前者。在这种情况下,T
的类型在运行时从 AbstractSpringMVCControllerTest
的 Class
对象中删除,但是 Class
DerpControllerTest
的对象确实提供了一种了解T
是什么的方法,因为它在编译时绑定(bind)了T
。
下面的类演示了如何访问T
的类型:
super .java
import java.lang.reflect.ParameterizedType;
public abstract class Super<T> {
protected T object;
@SuppressWarnings("unchecked")
public Class<T> getObjectType() {
// This only works if the subclass directly subclasses this class
return (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
}
子.java
public class Sub extends Super<Double> {
}
测试.java
public class Test {
public static void main(String...args) {
Sub s = new Sub();
System.out.println(s.getObjectType()); // prints "Class java.lang.Double"
}
}
关于java - 如何获取类型为 T 的字段的类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11158912/