2011-02-24 57 views
0

作为一个更大的项目的一部分,我试图实现一些我不太确定的事情,所以我非常希望看到有没有人有任何建议!对任意加载的类运行JUnit测试

整个系统:
作为一个整体,我的系统应该能够提供一个JUnit测试类,符合一些提供接口。然后给出的类不会实现这个接口,但需要检查它们是否能够(如果它们实现了所有必要的方法)。如果是这样,那么应该进行一些转换,以便JUnit测试类可以针对它运行。

到目前为止,我已经实现了:
- 运行JUnit测试用例并返回结果,使用JUnitCore

一个包 - 加载给出的路径和名称,使用的URLClassLoader
其他类的包

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

  1. 是否有可能再扩展此,例如,我可以ⅰ)验证它确实匹配的接口(I假设使用反射来检查对应的方法?),然后ⅱ)修改类,使得它可以使用JUnit测试类进行测试?

感谢您的任何建议,可能有助于解决部分问题。我很欣赏我的描述可能缺乏,所以如果您有任何额外的信息可以帮助您提供任何答案,请发表评论!

+0

你在这里试图解决的根本问题是什么? – 2011-02-24 21:30:03

回答

1

你可以用反射API做你想做的一切。听起来你应该从the tutorial开始,然后回到这里来回答特定的问题。给定一个Class对象,你可以检查它是否实现了给定的接口,创建它的一个实例,然后像对待其他类一样对待它。

编辑:我不认为我是从你的问题,但在这种情况下,你要寻找的反射API的Proxy一部分。

+0

谢谢,我知道这是事情的正确方向。然而,我将如何去了解我所描述的扩展版本,以便我需要i)查看类是否具有实现该接口的所有方法,ii)如果是这样,请将它看作是测试用例。 另外,当测试只与接口相匹配时,如何测试与JUnit中的接口相匹配的类? – obfuscation 2011-02-24 21:32:04

1

我怎么能运行JUnit测试对 一类确实实现了 接口时,测试的目的是 匹配接口

既然你有这个类可以使用isAssignableFrom方法由类这样

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

对于第二个问题,你可以检查每一个方法,看看1.如果存在一个方法,用同样的方法提供呐me定义在接口中,2.如果方法返回类型与接口相同,并且3.如果方法参数类型和长度相同。当然,2和3可能会很棘手。

在这一点上,我只是创建该接口(匿名或私人类)的一个实例,创建该匹配类的newInstance。并通过接口方法内的反射调用方法。

现在这就是你如何用反射来完成它。我不会提醒你反思,因为你可以想象:)

1

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

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

但是,我非常肯定,不可能在运行时修改类以添加接口。通过修改字节码可能是可能的,但我不知道这一点。

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

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在目标类中创建子类并在运行时添加接口。但代理方式并不是实施的核心。