台灣-景氣對策信號
景氣燈號
恐慌指數
初領失業救濟金人數
失業低於5週的短期失業人數
零售銷售年增率,個人耐久財消費支出年增率
耐久財訂單
私人固定資本投資年增率
製造業耐久財新訂單
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/applicationContext*.xml"})
@TransactionConfiguration(transactionManager="transactionManager", defaultRollback=true)
@Transactional
public abstract class SpringTXBaseTest {}
public class DaoTest extends SpringTXBaseTest {
@Autowired
private MemberDao dao;
@Test
public void testSelCountByAcc(){
String acc="7R6";
ClubMember member=OM.createPersistClubMember(acc);
dao.saveOrUpdate(member);
assertTrue(dao.selCountByAcc(acc)>0);
}
}
@Rollback(false)
@Test
public void testSelCountByAcc(){
String acc="7R6";
ClubMember member=OM.createPersistClubMember(acc);
dao.saveOrUpdate(member);
assertTrue(dao.selCountByAcc(acc)>0);
}
//測試 getBigHouses()所取出的房子都是>50坪的房子
@Test
public void testHousePing(){
List<House> houses=service.getBigHouses();
for (House house : houses) {
assertTrue(house.getPing().intValue()>50);
}
}
//測試 getBigHouses()所取出的房子都是>50坪的房子
@Test
public void testHousePing(){
List<House> houses=service.getBigHouses();
assertTrue(houses.size()>0); //一定要先測size
for (House house : houses) {
assertTrue(house.getPing().intValue()>50);
}
}
public Tenant getTenant(String name){
return findByName(name);
}
private Tenant findByName(String name){
return dao.getTenantByName(name);
}
@Test
public void testPrivateMethodByPublicMethod(){
String name = "Tom";
Tenant tenant=service.getTenant(name);
assertEquals(name, tenant.getName());
}
//default method
Tenant findByName(String name) {
return dao.getTenantByName(name);
}
package rent.report;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import rent.demo.Tenant;
public class DefaultMethodTest {
private RentServiceImpl service;
@Before
public void setUp() {
service = new RentServiceImpl();
}
@Test
public void testPrivate2DefaultMethod() {
String name = "Tom";
Tenant tenant = service.findByName(name);
assertEquals(name, tenant.getName());
}
}
Object object, String methodName, Class[] parameterTypes, Object[] args) @Test
public void testPrivateMethod() throws Throwable {
String name = "Tom";
Tenant tenant = (Tenant) PrivateAccessor.invoke(service, "findByName",
new Class[] { String.class }, new Object[] { name});
assertTrue(tenant.getName().equals(name));
}
最後要注意的是,當進行refactory 將此private method name變更時,因invoke 的第二個參數是使用method 的字串名稱,所以不會隨refactory 同步更換,要自己手動將此method 名稱變更為refactory後的名稱才行。
public class LottoMachine {
//選取到的幸運彩球
private List<ball> winBalls;
//開始執行,並由另一支Thread去進行選球的動作
public void actionRunner() throws InterruptedException {
winBalls = new ArrayList<ball>();
Thread t1 = new Thread(new LuckyRunner(winBalls));
t1.start();
}
public List<ball> getWinBalls() {
return winBalls;
}
}
public class LuckyRunner implements Runnable {
private List<ball> winBalls;;
private Ball ball;
private List<integer> ballNum = new ArrayList<integer>();
{
for (int i = 1; i < 50; i++) {
ballNum.add(i);
}
}
public LuckyRunner(List<ball> winBalls) {
this.winBalls = winBalls;
}
//選取5個不重複號的球.先暫停500ms再執行,摸擬洗球的程序。
@Override
public void run() {
try {
Thread.sleep(500);
for (int i = 0; i < 5; i++) {
int numberIndex = (int) (Math.random() * (49 - i));
int selNumber = ballNum.remove(numberIndex);
ball = new Ball();
ball.setBallNuber(selNumber);
winBalls.add(ball);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Test
public void testActionRunner() throws InterruptedException {
LottoMachine machine = new LottoMachine();
machine.actionRunner();
assertTrue(machine.getWinBalls().size() == 5); //will fail here!
for (Ball ball : machine.getWinBalls()) {
assertTrue(ball.getBallNuber() > 0 && ball.getBallNuber() <= 50);
System.out.println("ballNum=" + ball.getBallNuber());
}
}
@Test
public void testActionRunner() throws InterruptedException {
LottoMachine machine = new LottoMachine();
machine.actionRunner();
Thread.sleep(1000);
assertTrue(machine.getWinBalls().size() == 5);
for (Ball ball : machine.getWinBalls()) {
assertTrue(ball.getBallNuber() > 0 && ball.getBallNuber() <= 50);
System.out.println("ballNum=" + ball.getBallNuber());
}
}
public class LottoMachine {
private List<Ball> winBalls;
//回傳FutueTask,之後可用來檢查Thread的動作是否完成
public FutureTask<List<Ball>> actionCallabler() {
winBalls = new ArrayList<Ball>();
Callable<List<Ball>> callabler = new LuckyCallabler(winBalls);
FutureTask<List<Ball>> future = new FutureTask<List<Ball>>(callabler);
Thread t = new Thread(future);
t.start();
return future;
}
public List<Ball> getWinBalls() {
return winBalls;
}
}
public class LuckyCallabler implements Callable<List<Ball;>;> {
private List<Ball> winBalls;
private Ball ball;
private List<Integer> ballNum = new ArrayList<Integer;>();
{
for (int i = 1; i < 50; i++) {
ballNum.add(i);
}
}
public LuckyCallabler(List<Ball;> winBalls) {
this.winBalls = winBalls;
}
//選取5個不重複號的球.先暫停500ms再執行,摸擬洗球的程序。
@Override
public List<Ball> call() throws Exception {
try {
Thread.sleep(500);
for (int i = 0; i < 5; i++) {
int numberIndex = (int) (Math.random() * (49 - i));
int selNumber = ballNum.remove(numberIndex);
ball = new Ball();
ball.setBallNuber(selNumber);
winBalls.add(ball);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return winBalls;
}
}
@Test
public void testActionCaller() {
LottoMachine machine = new LottoMachine();
FutureTask<List<Ball>> future = machine.actionCallabler();
//使用While 來等待,當future.isDone為true,則進行驗證,驗證完則立刻break;否則會進入無窮迴圈
while (true) {
if (future.isDone()) {
assertTrue(machine.getWinBalls().size() == 5);
for (Ball ball : machine.getWinBalls()) {
assertTrue(ball.getBallNuber() > 0
&& ball.getBallNuber() <= 50);
System.out.println("ballNum=" + ball.getBallNuber());
}
break;
}
}
}
public class OnlyoneCipher {
private static OnlyoneCipher cipher;
private OnlyoneCipher() {}
public static OnlyoneCipher getInstance() {
if (cipher == null) {
cipher = new OnlyoneCipher();
}
return cipher;
}
public String encrypt(String source){
return doEncrypt(source);
}
}
public class MessageService {
public String encryptMsg(String source){
return OnlyoneCipher.getInstance().encrypt(source);
}
}
public class MessageService {
private OnlyoneCipher cipher;
public void setCipher(OnlyoneCipher cipher) {
this.cipher = cipher;
}
public String encryptMsg(String source){
return cipher.encrypt(source);
}
}
public class SingletonTest {
private MessageService service;
private OnlyoneCipher cipher;
@Before
public void setup(){
service=new MessageService();
//對OnlyoneCipher 做Mock
cipher=createMock(OnlyoneCipher.class);
service.setCipher(cipher);
}
@Test
public void testEncrypt(){
String source="Test String";
String encode="aaBBddaa";
expect(cipher.encrypt(source)).andReturn(encode);
replay(cipher);
String msg=service.encryptMsg(source);
verify();
assertEquals(encode,msg);
}
}
public interface IRemote {
Project getProject(String prjNo);
}
public class AppService implements IService{
public Long getPrjBudget(String prjNo){
IRemote remote=new RemoteProxy();
Project project=remote.getProject(prjNo);
return project.getBudget();
}
}
如果程式碼是這樣寫,那測試就不會過,因為測試環境根本無法呼叫到遠端服務,而且在測試環境中,程式也跑不起來。程式中,IRemote remote=new RemoteProxy() 就跟getPrjBudget(..) 這個方法綁死無法抽換。只要在方法中有用到 new 來建立服務,那這個服務就會跟這個方法綁死而無法抽換。public class AppService implements IService{
private IRemote remote;
public void setRemote(IRemote remote){
this.remote=remote;
}
public Long getPrjBudget(String prjNo){
Project project=remote.getProject(prjNo);
return project.getBudget();
}
}
public AppService getService(){
AppService service=new AppService();
if(isDevelopment()){
//取得測試環境的遠端服務
service.setRemote(getMockRemote());
}else{
//取得正式環境的遠端服務
service.setRemote(new RemoteProxy());
}
return service;
}
public class AppServiceTest{
private AppService service;
@Before
public void setup(){
service=new AppService();
service.setRemote(getMockRemote());
}
@Test
public void testGetPrjBudget(){
String prjNo="A123";
Long budget=service.getPrjBudget(prjNo);
assertTrue(budget>0);
}
}
@Controller
@RequestMapping("/rent")
public class RentController {
@Autowired
private IRentService service;
@RequestMapping(value = "/tenant", method = RequestMethod.POST)
public String tenantPage(Model model,HttpServletRequest request) {
Integer id=Integer.valueOf(request.getParameter("id"));
Tenant tenant=service.getTenant(id);
model.addAttribute("tenant", tenant);
return "tenant";
}
public void setService(IRentService service) {
this.service = service;
}
}
@Test
public void testRentController(){
RentController rc=new RentController();
rc.setService(new RentServiceImpl());
//model 和 HttpServletRequest 都是Interface,new 不出來
Model model=yourModelImpl();
HttpServletRequest request=yourRequestImpl();
String pageName=rc.tenantPage(model, request);
Assert.assertEquals("tenant",pageName);
}
@RequestMapping(value = "/tenant", method = RequestMethod.POST)
public String tenantPage(Model model,HttpServletRequest request) {
Integer id=Integer.valueOf(request.getParameter("id"));
//Tenant tenant=service.getTenant(id);
model.addAttribute("tenant", getTenant(id));
return "tenant";
}
//new extract method
public Tenant getTenant(Integer id){
return service.getTenant(id);
}
public class RentControllerTest {
private RentController rc;
private RentServiceImpl mockService;
@Before
public void setUp() {
rc = new RentController();
mockService = createMock(RentServiceImpl.class);
rc.setService(mockService);
}
@Test
public void testRentController() {
//test prepare
String key = "id";
String idVal = "2";
String attName = "tenant";
Tenant tenant = getTenant();
HttpServletRequest mockRequest = createMock(HttpServletRequest.class);
Model mockModel = createMock(Model.class);
//expect mock behavior
expect(mockRequest.getParameter(key)).andReturn(idVal);
expect(mockService.getTenant(Integer.valueOf(idVal))).andReturn(tenant);
expect(mockModel.addAttribute(attName, tenant)).andReturn(mockModel);
//replay mock behavior
replay(mockRequest);
replay(mockService);
replay(mockModel);
//action start
String pageName = rc.tenantPage(mockModel, mockRequest);
//verify mock behavior
verify(mockRequest);
verify(mockService);
verify(mockModel);
//assert test result
Assert.assertEquals(attName, pageName);
}
private Tenant getTenant() {
Tenant tenant = new Tenant(Identity.GENERAL);
tenant.setAge(31);
tenant.setCareer("IT");
tenant.setName("John");
return tenant;
}
}
public class ReportAgent {
//產生房客 Excel 報表資料
public boolean createExcelReport(Tenant tenant) throws IOException {
if (tenant != null) {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFRow row = sheet.createRow(0);
row.createCell(0).setCellValue(tenant.getName());
row.createCell(1).setCellValue(tenant.getAge());
row.createCell(2).setCellValue(tenant.getCareer());
FileOutputStream out = new FileOutputStream("report.xls");
wb.write(out);
out.close();
return true;
} else {
return false;
}
}
//產生房客 PDF 報表資料
public boolean createPdfReport(Tenant tenant) throws FileNotFoundException,
DocumentException {
if (tenant != null) {
Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream("report.pdf"));
document.open();
document.add(new Paragraph("Name:"+tenant.getName()));
document.add(new Paragraph("Age:"+tenant.getAge()));
document.add(new Paragraph("Career:"+tenant.getCareer()));
document.close();
return true;
} else {
return false;
}
}
//產生房客 Word 報表資料
public boolean crateWordReport(Tenant tenant) throws IOException{
//TODO
return true;
}
}
public enum ReportType {
EXCEL,PDF,WORD
}
public class RentServiceImpl implements RentService {
private ReportAgent reportAgent;
public void setReportAgent(ReportAgent reportAgent) {
this.reportAgent = reportAgent;
}
@Override
public void createReport(Tenant tenant, ReportType type)
throws IOException, DocumentException {
if (type == ReportType.EXCEL) {
reportAgent.createExcelReport(tenant);
} else if (type == ReportType.PDF) {
reportAgent.createPdfReport(tenant);
}
}
}
public class RentServiceTest {
private RentServiceImpl service;
@Before
public void setUp(){
service=new RentServiceImpl();
service.setReportAgent(new ReportAgent());
}
//無效的測試,無法判別錯誤
@Test
public void testCreateReport() throws IOException, DocumentException{
service.createReport(getTenant(), ReportType.PDF);
service.createReport(getTenant(), ReportType.WORD);
}
private Tenant getTenant() {
Tenant tenant=new Tenant(Identity.GENERAL);
tenant.setName("Jim");
tenant.setAge(30);
tenant.setCareer("Doctor");
return tenant;
}
}
public ReportType createReport(Tenant tenant, ReportType type)
throws IOException, DocumentException, ReportException {
if (type == ReportType.EXCEL) {
reportAgent.createExcelReport(tenant);
return ReportType.EXCEL;
} else if (type == ReportType.PDF) {
reportAgent.createPdfReport(tenant);
return ReportType.PDF;
}else {
throw new ReportException("Format Not Support");
}
}
@Test
public void testCreateReport() throws IOException, DocumentException, ReportException{
ReportType reportType=service.createReport(getTenant(), ReportType.PDF);
Assert.assertEquals(ReportType.PDF, reportType);
try {
service.createReport(getTenant(), ReportType.WORD);
Assert.fail();
} catch (Exception e) {
Assert.assertTrue(true);
}
}