我目前正在通过一个java教程,我正在介绍抽象类和使用J-Unit进行测试。
我有2个文件,AthleteTest& BikerTest,BikerTest扩展了AthleteTest.AthleteTest,包含了我不同测试的常用方法和变量,而BikerTest包含了具体细节。
ATHLETETEST
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public abstract class AthleteTest
{
private Athlete a1;
private Athlete a2;
protected String _name = "Test Athlete";
protected int _age = 32;
protected int _racerId = 987654;
public abstract Athlete getAthlete();
public abstract Athlete getExplicitAthlete();
public AthleteTest()
{
a1 = getAthlete();
a2 = getExplicitAthlete();
}
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test
public void testConstructors()
{
assertNotNull("Default Runner could not be created", a1);
assertNotNull("Explicit Runner could not be created", a2);
assertEquals("Name not set correctly on a2"
, _name
, a2.getName());
assertEquals("Age not set correctly on a2"
, _age
, a2.getAge());
assertEquals("RacerID not set correctly on a2"
, _racerId
, a2.getRacerId());
}
@Test
public void testGetSetName()
{
a1.setName(_name);
assertEquals("The name could not be set as expected"
, _name
, a1.getName());
}
@Test
public void testGetSetAge()
{
a1.setAge(_age);
assertEquals("The age could not be set as expected"
, _age
, a1.getAge());
}
@Test
public void testGetSetRacerId()
{
a1.setRacerId(_racerId);
assertEquals("The racerId could not be set as expected"
, _racerId
, a1.getRacerId());
}
public abstract void testPerformRaceActivity();
@Test
public void testToString()
{
a1.setName(_name);
a1.setAge(_age);
a1.setRacerId(_racerId);
String rts = a1.toString();
assertTrue("To String does not contain name"
, rts.contains(_name));
assertTrue("To String does not contain age"
, rts.contains(String.format("%d", _age)));
assertTrue("To String does not contain racer id"
, rts.contains(String.format("%d", _racerId)));
String rc = a1.getClass().toString();
assertTrue("To String does not contain class"
, rts.contains(rc));
}
}
BIKERTEST
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class BikerTest extends AthleteTest
{
private Biker r;
private String raceActivity = "Biking";
private boolean usesClips = false;
@Override
public Athlete getAthlete() {
return new Biker();
}
@Override
public Athlete getExplicitAthlete() {
return new Biker(_name,_age,_racerId,usesClips);
}
@Before
public void setUp()
{
r = new Biker();
}
@After
public void tearDown()
{
r = null;
}
@Test
public void testConstructors()
{
super.testConstructors();
Biker r2 = new Biker(_name, _age, _racerId, usesClips);
assertNotNull("Explicit Biker could not be created", r2);
assertEquals("Name not set correctly on R2"
, _name
, r2.getName());
assertEquals("Age not set correctly on R2"
, _age
, r2.getAge());
assertEquals("RacerID not set correctly on R2"
, _racerId
, r2.getRacerId());
assertEquals("UsesClips not set correctly on R2"
, usesClips
, r2.getUsingClips());
}
@Test
public void testGetSetUsingClips()
{
r.setUsingClips(usesClips);
assertEquals("The clips could not be set as expected"
, usesClips
, r.getUsingClips());
}
@Test
public void testPerformRaceActivity()
{
String pra = r.performRaceActivity();
assertTrue("Perform race activity did not contain activity"
, pra.contains(raceActivity));
}
@Test
public void testToString()
{
super.testToString();
r.setName(_name);
r.setAge(_age);
r.setRacerId(_racerId);
r.setUsingClips(usesClips);
String rts = r.toString();
assertTrue("To String does not contain using clips"
, rts.contains(String.format("%b", usesClips)));
assertTrue("To string does not contain performRaceActivity"
, rts.contains(raceActivity));
}
}
现在,虽然我的文件和代码正在运行(它是从提供的示例中获取的),但我无法弄清楚它的工作原理,因为教程没有详细说明如何测试已执行。
QN1 为什么我需要抽象类AthleteTest中的构造函数?我的理解是因为它是抽象的,它不会被实例化,因此不需要构造函数,因为构造函数只有在实例化类时才会起作用。
QN2 测试是如何进行的;什么是测试顺序?例如,当我运行BikerTest时,虽然我重写了GetAthlete和GetExplicitAthlete类,但我实际上并没有运行代码中的方法。但是为什么当我运行代码时,运行方法。 JUnit是否只是默认运行所有方法?
QN3 当我运行BikerTest时,超级运动员测试如何实例化和工作?例如,在BikerTest中,我调用了super-这是AthleteTest.Is AthleteTest在我调用super时实例化/创建 - 并且生成的对象存储在a1& amp; a2,还是在某个时候和其他地方创建的?
提前感谢您提供的任何澄清和解释!
答案 0 :(得分:2)
为什么我需要抽象类AthleteTest中的构造函数?我的理解是因为它是抽象的,所以不会被实例化
那是对的。无法实例化抽象类。虽然,这并不意味着抽象类不能有构造函数。如果您没有向类中添加构造函数,编译器将为您添加默认的无参数构造函数。对于抽象类也是如此。此外,Java中的每个构造函数都有一个隐式super()
调用,因为它的第一行调用了父类的构造函数(包括编译器添加的默认构造函数)。在您的示例中,BikerTest
没有显式构造函数。因此,编译器将以下构造函数添加到BikerTest
类:
public BikerTest() {
super();
}
只要您运行BikerTest
JUnit
课程,JUnit
就会在{{1}中创建BikerTest
课程和super()
来电的实例构造函数将导致调用BikerTest
类的构造函数。
例如,当我运行BikerTest时,我覆盖了GetAthlete和 GetExplicitAthlete类,我实际上并没有在中运行方法 code.Yet为什么当我运行代码时,方法运行
如前所述,AthleteTest
中的super()
调用会导致调用BikerTest
类的无参数构造函数。 AtheleteTest
类调用AtheleteTest
和getAthlete()
方法。虽然这些方法是抽象的,但它们已在getExplicitAthlete()
类中被覆盖。将调用BikerTest
类中的方法,因为创建的对象属于类BikerTest
当我跑步时,超级运动员测试如何实例化和工作 BikerTest?例如,在BikerTest中,我调用了super - 这是 AthleteTest.Is AthleteTest在i时实例化/创建 拨打超级电话 - 结果对象存储在a1& a2, 或者它是在某个时间和其他地方创建的?
没有。使用BikerTest
调用方法或使用super
访问字段不会导致超类被实例化(无论它是否是抽象的)。在super
方法中为r
变量分配了一个对象,这是setUp
在运行任何测试之前将调用的第一种方法。实例化JUnit
并调用a1
无参数构造函数时,a2
和BikerTest
变量被赋予一个对象(如前所述)
答案 1 :(得分:0)
为什么我需要抽象类AthleteTest中的构造函数?我的 理解是因为它是抽象的,它不会 实例化,因此不需要构造函数 构造函数只有在实例化类时才会发挥作用。
抽象类无法直接实例化 - 它们必须由非抽象类子类化,并且可以实例化该子类。但是,当您实例化一个子类时,超类的所有字段也是您创建的对象的一部分。而且,抽象超类的构造函数被称为。
测试是如何完成的;什么是测试顺序?对于 例如,当我运行BikerTest时,我覆盖了GetAthlete和 GetExplicitAthlete类,我实际上并没有在中运行方法 code.Yet为什么当我运行代码时,方法运行。是否 JUnit默认只运行所有方法吗?
当您使用JUnit 4作为测试运行类时,所有使用@Test注释的方法都将作为测试方法运行。使用@Before注释的方法在每次测试运行之前运行,而@After注释的方法在每次测试之后运行。
您可以使用更多注释,例如@BeforeClass和@AfterClass。
当我跑步时,超级运动员测试如何实例化和工作 BikerTest?例如,在BikerTest中,我调用了super - 这是 AthleteTest.Is AthleteTest在i时实例化/创建 拨打超级电话 - 结果对象存储在a1& a2, 或者它是在某个时间和其他地方创建的?
不,在您实例化子类时实例化超类。实际上,您创建了一个对象,该对象包含您实例化及其所有超类的子类中的所有字段。因此,当JUnit为您创建BikerTest
的实例时,来自AthleteTest
的所有字段(作为对象的一部分创建的BikerTest
的超类。{{1}的构造函数也被称为。
答案 2 :(得分:0)
抽象类中的构造函数可用于初始化您的类,例如,如果您使用final属性。子类中的构造函数可以调用抽象类的一个构造函数。