1

目标:在典型的企业 Java 环境中测试 TDD。

语境 :

使用的框架(即使它是矫枉过正,我练习基于项目的学习):

  • DAO:休眠
  • 春季国际奥委会
  • 前端:Spring MVC + Twitter Boostrap(如果可能)
  • TDD:JUnit
  • 数据库:PostgreSQL

我的项目是一个简单的计费系统,可以帮助自由职业者创建、编辑和打印/发送账单给客户。

创建和配置我的项目后,我不知道从哪里开始。假设我的第一个功能是创建具有唯一编号和标题的账单。

问题:我应该首先测试什么?

  • 具有 createBill(String title) 方法的域层会生成一个唯一的序列号?我会模拟数据库层。
  • 首先是 UI,模拟服务层?我不知道该怎么做。

提前感谢您的回答,

干杯

4

1 回答 1

4

从测试开始:-)

你的系统是做什么的?

public class BillingSystemTest {
    @Test
    public void generatesBills() {
        Bill bill = new BillingSystem().generate()
        assertNotNull(bill)
    }
}

第一次测试完成!

让它通过,继续下一个测试......

@Test
public void generatesAnInvoiceNumberForEachBill() {
    Bill bill = new BillingSystem().generate()
    assertEquals(1, bill.getNumber())
}

// ...and the next
@Test
public void generatesUniqueInvoiceNumbersForEachBill() {
    BillingSystem bs = new BillingSystem()
    assertEquals(1, bs.generate().getNumber())
    assertEquals(2, bs.generate().getNumber())
}

@Test
public void generatesAnInvoiceSubjectWhenNoneIsSpecified() {
    Bill bill = new BillingSystem().generate()
    assertEquals("Invoice #1 from ACME Corp.", bill.getSubject())
}

@Test
public void allowsForCustomSubjectsOnBills() {
    Bill bill = new BillingSystem().generate("Custom subject")
    assertEquals("Custom subject", bill.getSubject())
}

我显然已经跳过了这里的重构步骤,但是现在您已经有了测试以及随之而来的代码,您需要对其进行评估以获得更多机会。我想象代码看起来像这样。

public class BillingSystem {
    private nextInvoiceNumber = 1;

    public Bill generate() {
        return generate("Invoice #" + nextInvoiceNumber + " from ACME Corp.");
    }

    public Bill generate(String subject) {
        Bill bill = new Bill(nextInvoiceNumber, subject)
        nextInvoiceNumber++
        return bill;
    }
}

看这段代码,似乎没问题,但可能违反了单一职责原则(SRP)。这里BillingSystem生成账单以及管理发票编号。这是一个重构的机会。重构后,您的设计可能如下所示:

public class BillingSystem {
    private InvoiceNumbering invoiceNumbering = new InvoiceNumbering()

    public Bill generate() {
        return generate("Invoice #" + invoiceNumbering.peekNext() + " from ACME Corp.");
    }

    public Bill generate(String subject) {
        Bill bill = new Bill(invoiceNumbering.generateNext(), subject)
        nextInvoiceNumber++
        return bill;
    }
}

你的设计更好,你的测试都通过了。接下来要做的是重构测试以从中删除实现细节。他们最终可能看起来像:

@Test
public void generatesBills() {
    Bill bill = new BillingSystem().generate()
    assertNotNull(bill)
}

@Test
public void generatesAnInvoiceNumberForEachBill() {
    // Using hand rolled mocks
    MockInvoiceNumbering in = new MockInvoiceNumbering()
    in.generateNextShouldReturn(4)

    Bill bill = new BillingSystem(in).generate()
    assertEquals(4, bill.getNumber())
}

@Test
public void generatesUniqueInvoiceNumbersForEachBill() {
    MockInvoiceNumbering in = new MockInvoiceNumbering()

    BillingSystem bs = new BillingSystem(in)

    bs.generate();
    bs.generate();

    assertEquals(2, in.numberOfTimesGenerateNextWasCalled)
}

@Test
public void generatesAnInvoiceSubjectWhenNoneIsSpecified() {
    Bill bill = new BillingSystem().generate()
    assertEquals("Invoice #1 from ACME Corp.", bill.getSubject())
}

@Test
public void allowsForCustomSubjectsOnBills() {
    Bill bill = new BillingSystem().generate("Custom subject")
    assertEquals("Custom subject", bill.getSubject())
}

作为此重构的一部分,您可能会围绕您的InvoiceNumbering类创建一些测试。

希望这是一个足够的开始。留下了很多东西。:-)

希望有帮助!

布兰登

于 2012-10-05T21:23:32.127 回答