软件构造实验遇到的问题
在进行学校的软件构造实验时,我遇到了一些问题,故以此方式记录下来,希望以后自己有能力解决。
JUnit的使用
在使用JUnit写测试类的时候出现了一种奇怪的现象:对于某一方法,明明写了测试方法,结果用覆盖率运行的时候却发现这个方法根本未被覆盖,即便是单独运行对应的测试方法依然显示未被覆盖。
public class MyObject {
public MyObject() {
}
public void add() {
System.out.println(2);
}
}
public class demo {
public demo(){
}
public void add(){
System.out.println(1);
}
}
public abstract class demoTest {
@Test
public void testforadd(){
demo d= new demo();
d.add();
}
}
public class MyObjectTest extends demoTest{
@Test
public void testforadd(){
MyObject m=new MyObject();
m.add();
}
}
运行demoTest之后的结果如下
这说明最终被调用的是MyObject中的add方法。此时我认为是由于MyObjectTest重写了demoTest中的testforadd方法,但是当我把demoTest从抽象类改为实体类之后,运行结果如下:
这说明最终被调用的是demo中的add方法。此时我产生疑问:以上两种情况都是MyObjectTest重写了demoTest中的testforadd方法,那为何最终调用的方法不一样呢?
仔细观察之后,我注意到在运行结果左边的不同之处:虽然我两次点击的都是demoTest的运行,但是在demoTest为抽象类时,最终运行的是MyObjectTest;在demoTest为实体类时,最终运行的是demoTest。
由此我联想到了在写功能代码时抽象类和实体类的区别:抽象类不能有构造方法;实体类可以有构造方法。也就是说,我在运行测试类的时候,相当于系统内部自动为我写好了客户端代码,这个代码会为所有测试类都建立一个对象,然后再运行这些对象中的所有测试方法。当demoTest为抽象类时,系统会用MyObjectTest来为其构造对象,因此便会使用重写后的方法;当demoTest为实体类时,系统会用demoTest来为其构造对象,因此便会使用重写前的方法。
为了佐证以上结论,我将demoTest改回抽象类,将MyObjectTest删除,运行demoTest,运行结果如下:
结果进一步说明我的观点是正确。
不过以上结论都是我基于现有的几个实例瞎总结,真正的原因恐怕还是得去翻阅JUnit的源码,希望我以后有能力去实现。