对任意加载的类运行JUnit测试

时间:2011-02-24 21:13:12

标签: java reflection junit

作为一个大项目的一部分,我正在尝试实现一些我不确定的可能性,所以我很想看看是否有人有任何建议!

整个系统:
总的来说,我的系统应该能够提供一个JUnit测试类,它匹配一些提供的接口。然后将给出不实现此接口的类,但需要检查它们是否能够(如果它们实现了所有必要的方法,则为a.k.a.)。如果是这样,应该进行一些转换,以便可以针对它运行JUnit测试类。

到目前为止,我已实施:
- 使用URLClassLoader
加载给定路径和名称的其他类的包 - 运行JUnit测试用例并使用JUnitCore

返回结果的包

问题:
1.首先,当测试设计为与接口匹配时,如何针对实现接口的类运行JUnit测试?我如何(在运行时)指示接口测试的实例是加载的类?

  1. 是否有可能扩展它,以便我可以i)验证它是否与接口匹配(我假设使用Reflection来检查相应的方法?)然后ii)修改该类以便可以使用它来测试JUnit测试类?
  2. 感谢任何可能有助于解决部分问题的建议。我感谢您的描述可能缺乏,所以如果您有任何可以帮助您给出任何答案的额外信息,请发表评论!

4 个答案:

答案 0 :(得分:1)

您可以使用反射API执行所需操作。听起来你应该从the tutorial开始,然后回到这里寻找具体问题。给定一个Class对象,您可以检查它是否实现了给定的接口,创建它的实例,然后将其视为任何其他类。

编辑:我认为我没有从你的问题中得到这个,但在这种情况下,你正在寻找反射API的Proxy部分。

答案 1 :(得分:1)

  

我怎么能运行JUnit测试   一个确实实现的类   测试设计时的界面   匹配界面

由于您拥有该类,因此可以使用该类提供的isAssignableFrom方法,以便

Class loadedJunitClass = clazz;
MyInterface impl = null;
if(MyInterface.class.isAssignableFrom(loadedJunitClass )){
    impl = (MyInterface) loadedJunitClass.newInstance();
}

对于第二个问题,您可以检查每个方法并查看1.如果存在具有与接口中定义的方法名称相同的方法,则2.如果方法返回类型与接口相同,则为3.如果方法参数类型和长度是相同的。当然,2和3可能很难做到正确。

此时我只想创建该接口的实例(匿名或私有类),创建该匹配类的newInstance。并通过接口方法中的反射调用方法。

现在,你可以通过反思来完成它。我不是想象你想象的反思:)

答案 2 :(得分:1)

问题的第一部分;如果您要为要测试的类加载了Class实例,则可以使用newInstance()构造一个(如果它具有默认构造函数),或者如果需要传递参数,则可以通过getConstructor方法构造。您应该能够从类加载器中获取此Class实例。

第二部分。您应该能够通过getMethods()(再次在Class实例上)检查公共方法,然后查看返回的数组以获取所需的方法。 Method类上有一些方法可以返回有关参数,异常和返回类型的信息,以验证它们是否符合您的要求。

但是,我很确定在运行时无法修改类来添加接口。通过修改字节代码可能是可能的,但我不知道。

另一种方法是编写测试以通过反射调用所有方法,然后对象的类型只是它具有正确的方法(您已经检查过)并不重要。

答案 3 :(得分:1)

如果你想让任意类在运行时实现给定接口,如果它的公共API与接口匹配,那么你在Java中有几个选项。创建java.lang.Proxy以桥接目标类,公开YourInterface是最简单的方法。

YourInterface i = (YourInterface) Proxy.newProxyInstance(
        this.getClass().getClassLoader(), 
        new Class[]{YourInterface.class},
        new InvocationHandler() {

    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        //run method on your target class here using reflection
    }

 });

您还可以在AspectJ中使用mixins,或者使用CGLIB将目标类子类化,并在运行时添加接口。但是代理方法并不是那么难以实现的。