我正在学习一个教授服务层概念的旧Java教程,我的程序是一个非常简单的程序,它将创建一个Bills列表及其截止日期。我遇到的问题是为工厂方法创建JUnit测试。
首先是Bill Constructor
public Bill(String bname, Double bamount, Date bdate, String bfrequency){
this.billName = bname;
this.billAmount = bamount;
this.billDueDate = bdate;
this.frequency = bfrequency;
}
接下来是保存和获取这些账单的界面
public interface IBill {
public void save(Bill bill);
public Bill read(Bill readbill);
}
请耐心等待,接下来是接口的具体实现,暂时已经删除,尚未实现
public class BillSvcImpl implements IBill {
@Override
public void save(Bill bill) {
System.out.println("Entering the Store BillInfo method");
}
@Override
public Bill read(Bill readbill) {
System.out.println("Entering the Read BillInfo method");
return null;
}
}
然后有工厂方法将创建/调用具体实现
public class Factory {
public IBill getBillInfo(){
return new BillSvcImpl();
}
}
然后最后JUnit测试了我被困的地方
public class BillSvcTest extends TestCase {
private Factory factory;
@Before
public void setUp() throws Exception {
super.setUp();
factory = new Factory();
}
@test
public void testSaveBill(){
IBill bill = factory.getBillInfo();
Bill nanny = new Bill("Nanny",128d,new Date(6/28/2013),"Montly");
bill.save(nanny);
//what goes here??, Assert??
}
@test
public void testReadBill(){
//How can I write a Test for this??
//Please help
}
}
指令是
为您的服务创建一个JUnit测试,测试应该使用Factory来获取服务,在setUp()方法中实例化。
我的服务/接口有两种方法save和get,在开始实际实现之前,如何为这些创建测试。
感谢任何帮助。 谢谢
答案 0 :(得分:3)
首先,don't extend TestCase
- 而是使用JUnit 4.x。
其次,我对一种有副作用的方法感到非常不满。我们没有理由修改您的save
方法以返回boolean
而不是void
;你只需要采用另一种方法来测试方法。
第三,我认为简单的单元测试无法涵盖此方法的保存功能。读起来的东西会在某个地方持久存在,更适合某种集成测试(使用数据库,确保文件存在且内容正确等)。
单元测试时要回答的主要问题是“给定此参数时此方法调用的预期结果是什么?”当我们致电save
时,我们会发生什么?我们写信给数据库吗?我们是否序列化内容并写入文件?我们写XML / JSON /纯文本了吗?首先必须回答这个问题,然后可以围绕它编写一个有用的测试。
同样适用于read
- 当我尝试阅读账单时,我期望收到什么作为输入?传入Bill
对象并返回Bill
对象可以获得什么? (为什么外面的来电者会想到我想读的账单?)
你必须充实你对这些方法的期望。这是我用来编写单元测试的方法:
在编写单元测试之前,您必须定义您的期望。
答案 1 :(得分:1)
IMO save
方法应该返回一些内容,说明Bill
是否已保存。我会像这样保存方法
public boolean save(Bill bill) {
System.out.println("Entering the Store BillInfo method");
boolean result = false;
try {
//..... saving logic
result = true;
}
catch(Exception e) {
result = false;
e.printStackTrace();
}
return result;
}
并在测试用例中做了一个断言
@Test
public void testSaveBill(){
//Success
IBill bill = factory.getBillInfo();
Bill nanny = new Bill("Nanny",128d,new Date(6/28/2013),"Montly");
assertTrue(bill.save(nanny));
//Failure
assertFalse(bill.save(null));
}
答案 2 :(得分:0)
通常,read()和store()的实现涉及与外部系统(如数据库,文件系统)的集成。这使得测试与外部系统齐头并进。
@Test
public void insertsBillToDatabase() {
//setup your database
bill.store(aBill);
//fetch the inserted bill then assert
}
这些测试主要关注您的组件是否在外部系统上进行正确的abstration。
依赖于外部系统的测试很昂贵,因为它们相对较慢且难以设置/清理。如果商店()中存在一些复杂的业务逻辑,您最好将业务包含和集成问题分开。
public void store(Bill bill) {
//business logic
billDao.save(bill); // delegate to an injected dao, you can replace it with a test double in test code
}
@Test
public void doesSthToBillBeforeSave() {
//replace your billDao with a stub or mock
bill.store(aBill);
//assert the billDao stub / mock are correctly invoked
//assert bill's state
}