为什么我需要抽象类中的构造函数?

时间:2015-05-24 14:20:18

标签: java testing junit junit4

我目前正在通过一个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,还是在某个时候和其他地方创建的?

提前感谢您提供的任何澄清和解释!

3 个答案:

答案 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类调用AtheleteTestgetAthlete()方法。虽然这些方法是抽象的,但它们已在getExplicitAthlete()类中被覆盖。将调用BikerTest类中的方法,因为创建的对象属于类BikerTest

  

当我跑步时,超级运动员测试如何实例化和工作   BikerTest?例如,在BikerTest中,我调用了super - 这是   AthleteTest.Is AthleteTest在i时实例化/创建   拨打超级电话 - 结果对象存储在a1& a2,   或者它是在某个时间和其他地方创建的?

没有。使用BikerTest调用方法或使用super访问字段不会导致超类被实例化(无论它是否是抽象的)。在super方法中为r变量分配了一个对象,这是setUp在运行任何测试之前将调用的第一种方法。实例化JUnit并调用a1无参数构造函数时,a2BikerTest变量被赋予一个对象(如前所述)

答案 1 :(得分:0)

  1.   

    为什么我需要抽象类AthleteTest中的构造函数?我的   理解是因为它是抽象的,它不会   实例化,因此不需要构造函数   构造函数只有在实例化类时才会发挥作用。

  2. 抽象类无法直接实例化 - 它们必须由非抽象类子类化,并且可以实例化该子类。但是,当您实例化一个子类时,超类的所有字段也是您创建的对象的一部分。而且,抽象超类的构造函数被称为。

    1.   

      测试是如何完成的;什么是测试顺序?对于   例如,当我运行BikerTest时,我覆盖了GetAthlete和   GetExplicitAthlete类,我实际上并没有在中运行方法   code.Yet为什么当我运行代码时,方法运行。是否   JUnit默认只运行所有方法吗?

    2. 当您使用JUnit 4作为测试运行类时,所有使用@Test注释的方法都将作为测试方法运行。使用@Before注释的方法在每次测试运行之前运行,而@After注释的方法在每次测试之后运行。

      您可以使用更多注释,例如@BeforeClass和@AfterClass。

      1.   

        当我跑步时,超级运动员测试如何实例化和工作   BikerTest?例如,在BikerTest中,我调用了super - 这是   AthleteTest.Is AthleteTest在i时实例化/创建   拨打超级电话 - 结果对象存储在a1& a2,   或者它是在某个时间和其他地方创建的?

      2. 不,在您实例化子类时实例化超类。实际上,您创建了一个对象,该对象包含您实例化及其所有超类的子类中的所有字段。因此,当JUnit为您创建BikerTest的实例时,来自AthleteTest的所有字段(作为对象的一部分创建的BikerTest的超类。{{1}的构造函数也被称为。

答案 2 :(得分:0)

抽象类中的构造函数可用于初始化您的类,例如,如果您使用final属性。子类中的构造函数可以调用抽象类的一个构造函数。