从测试开始:-)
你的系统是做什么的?
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类创建一些测试。
希望这是一个足够的开始。留下了很多东西。:-)
希望有帮助!
布兰登