OOP 的一个很好的机制是使用抽象类,抽象类是不能被实例化的,只能提供给派生类一个接口。设计人员通常使用抽象类来强迫实现人员从基类派生,这样可以确保新的类包含一些期待的功能。

Junit 对抽象类的测试中再次引入工厂设计模式,其测试思想是:抽象类不能被实例化,所以使用具体类测试抽象类是不可以的。因此,构造抽象类的测试类必须也是抽象的。该类需要强制声明两种类型的抽象方法。第一类抽象方法即工厂方法,返回所有被测试抽象类的具体子类实例,第二类定义抽象方法返回所有被测试抽象类的具体子类行为期望值。如下面代码, Commodity 类是一个商品抽象类,该类的抽象方法描述具体如下:

getCommodityName(): 取商品名称

changerName(): 修改商品名称

getCommodityPrice(): 取商品价格

changerPrice(): 修改商品价格

Commodity 类具体代码如下

package com.fastpiont;

public abstract class Commodity {

public abstract String getCommodityName();// 取得商品名称

public abstract void changerName(String newName);// 修改商品名称

public abstract double getCommodityPrice();// 取得商品价格

public abstract void changerPrice( double newPrice);// 修改商品价格

CommodityTestCase Commodity 抽象类的测试类,同样该类被声明为抽象的。 Commodity 抽象类包含了 getCommodity() 工厂方法返回具体类实例,因为这才是真正的被测试对象。 PrepareAndGetExpectedName() PrepareAndGetExpectedPrice() PrepareAndChangerExpectedName() PrepareAndChangerExpectedPrice() 四组方法分别返回具体类实例行为的期望值,即该实例行为的判断基准,具体代码如下:

package com.fastpiont;

import static org.junit.Assert.*;

import org.junit.After;

import org.junit.Before;

import org.junit.Test;

public abstract class CommodityTest {

Commodity comm;

public abstract Commodity getCommodity();// 工厂方法,返回具体商品类

public abstract String prepareAndGetExpectedName();// 返回期望值

public abstract double prepareAndGetExpectedPrice();

public abstract String repareAndChangerExpectedName();// 返回更改期望值

public abstract double prepareAndChangerExpectedPrice ();

@Before

public void setUp() throws Exception {

comm = getCommodity();

@After

public void tearDown() throws Exception {

@Test

public void testGetCommodityName() {

String expected = prepareAndGetExpectedName();

String received = getCommodity().getCommodityName();

assertEquals (expected, received);

@Test

public void testChangerName() {

comm.changerName(repareAndChangerExpectedName());

assertEquals (repareAndChangerExpectedName(), comm.getCommodityName());

@Test

public void testGetCommodityPrice() {

double expected = prepareAndGetExpectedPrice();

double received = getCommodity().getCommodityPrice();

assertEquals (expected, received);

@Test

public void testChangerPrice() {

comm.changerPrice( prepareAndChangerExpectedPrice ());

assertEquals ( prepareAndChangerExpectedPrice (), comm.getCommodityPrice());

现在根据抽象类测试思想构造一个集成了 Commodity 抽象类的具体商品子类 Commodity_Book Commodity_Book 类的构造方法有两个传参,即根据传入的书籍名称值和书籍单价值生成一本书实例。 Commodity_Book 类不鼓励直接修改书籍的属性,但是可以通过连歌公共方法 changerName() changerPrice() 来实现,具体代码如下:

package com.fastpiont;

public class Commodity_Book extends Commodity {

private String book_name;

private double book_price;

public Commodity_Book(String bookname, double bookprice) {

book_name = bookname;

book_price = bookprice;

public void changerName(String newName) {

setBook_name(newName);

public void changerPrice( double newPrice) {

setBook_price(newPrice);

public String getBook_name() {

return book_name;

private void setBook_name(String book_name) {

this .book_name = book_name;

public double getBook_price() {

return book_price;

private void setBook_price( double book_price) {

this .book_price = book_price;

@Override

public String getCommodityName() {

// TODO Auto-generated method stub

return getBook_name();

@Override

public double getCommodityPrice() {

// TODO Auto-generated method stub

return getBook_price();

Commodity_BookTestCase 类继承了 CommodityTestCase 抽象类,整个类显得非常简单,包括工厂方法返回一个具体的 Commodity 实例和四个针对该实例的期望值设定,具体代码如下:

package com.fastpiont;

import static org.junit.Assert.*;

import org.junit.After;

import org.junit.Before;

import org.junit.Ignore;

import org.junit.Test;

public abstract class CommodityTest {

Commodity comm;

public abstract Commodity getCommodity();// 工厂方法,返回具体商品类

public abstract String prepareAndGetExpectedName();// 返回期望值

public abstract double prepareAndGetExpectedPrice();

public abstract String repareAndChangerExpectedName();// 返回更改期望值

public abstract double prepareAndChangerExpectedPrice();

@Before

public void setUp() throws Exception {

comm = getCommodity();

@After

public void tearDown() throws Exception {

@Test

public void testGetCommodityName() {

String expected = prepareAndGetExpectedName();

String received = comm.getCommodityName();

assertEquals(expected, received);

@Test

public void testChangerName() {

comm.changerName(repareAndChangerExpectedName());

assertEquals(repareAndChangerExpectedName(), comm.getCommodityName());

@Test

public void testGetCommodityPrice() {

double expected = prepareAndGetExpectedPrice();

double received = comm.getCommodityPrice();

assertEquals(expected, received, 0.001);

@Test

public void testChangerPrice() {

comm.changerPrice(prepareAndChangerExpectedPrice());

assertEquals(prepareAndChangerExpectedPrice(),

comm.getCommodityPrice(), 0.001);

这种针对抽象类的测试方法是 Junit 推导者所主张的,好处在于该抽象类的所有具体子类都不用在测试抽象类中的所有抽象发发(抽象类中的具体方法除外,因为该方法可能被具体子类覆盖),符合 XP 测试的接口测试定义。

专注于自动化、性能研究,博客为原创,转载请注明文章来源于:http://www.cnblogs.com/Automation_software/ 只求在IT界有一个清闲的世界让我静心的去专研,不求功名利禄,只为心中的那份成就感及自我成长、自我实现的快感。