2013年3月31日 星期日

JMock - 參考文章與網站





JUnit4 与 JMock 之双剑合璧:

http://www.ibm.com/developerworks/cn/java/j-lo-junit4jmock/


JMock官方網站Cookbook:
http://jmock.org/cookbook.html


良葛格:
http://caterpillar.onlyfun.net/Gossip/JUnit/JMock.html



In-process Web Integration Tests with Jetty and JWebUnit

http://johannesbrodwall.com/2006/12/10/in-process-web-integration-tests-with-jetty-and-jwebunit/

2013年3月30日 星期六

JMock初體驗


以下範例為測試 PreMathM.all() 的行為:

  1.  呼叫MathM.returnOne()
  2. 檢驗return Value == 1
  3. 呼叫_mockMathM.echo(3)
  4. 檢驗return Value == 3

 
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.Sequence;
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;


@SuppressWarnings("deprecation")
@RunWith(JMock.class)
public class JMockTest {


 Mockery _context = new JUnit4Mockery(){{
        setImposteriser(ClassImposteriser.INSTANCE);
    }};
 MathM _mockMathM  = _context.mock(MathM.class);

 public class PreMathM{
  MathM _mathm;
  public PreMathM(MathM mathm){
   _mathm = mathm;
  }
  public void all(int echov){
   _mathm.returnOne();
   _mathm.echo(echov);
  }  
 }
 public class MathM {
  public int returnOne() {
   return 1;
  }

  public int echo(int echov) {
   return echov;
  }
 }

 @Before
 public void setUp() throws Exception {
  
 }

 @After
 public void tearDown() throws Exception {
 }

 @Test
 public void testSequenceOneEcho() {
  final Sequence sequenceOneEcho = _context.sequence("sequenceOneEcho");
  _context.checking(new Expectations() {
   {
    atLeast(1).of(_mockMathM).returnOne();
    inSequence(sequenceOneEcho);
    will(returnValue(1));
//    oneOf(_mockMathM).echo(3);
    atLeast(1).of(_mockMathM).echo(3);
    inSequence(sequenceOneEcho);
    will(returnValue(3));
   }
  });
  
  PreMathM mall = new PreMathM(_mockMathM);
  mall.all(3);
 }

}

上述範例中,每次呼叫inSequence(sequenceOneEcho),都是為了確保每一個行為是【按順序】執行呼叫

JMock - java.lang.IllegalArgumentException: ... is not an interface


解法:


出現:java.lang.IllegalArgumentException: unittest.MathM is not an interface
at java.lang.reflect.Proxy.getProxyClass(Unknown Source)

....


(unittest.MathM為自訂預測試Class)


Mockery _context = new JUnit4Mockery();

改為


 
 Mockery _context = new JUnit4Mockery(){{
        setImposteriser(ClassImposteriser.INSTANCE);
    }};



探討:

看到exception上其實說得很明白 unittest.MathM is not an interface,就大概可以猜到若要將我們欲使用的Mock物件(這裡為MathM)變成可使用的,就得為interface;

以下是Mockery.setImposteriser()的doc:


Changes the imposteriser used to adapt mock objects to the mocked type. The default imposteriser allows a test to mock interfaces but not classes, so you'll have to plug a different imposteriser into the Mockery if you want to mock classes.



因此對於已經為concreate class的 object來說,就得另外使用  setImposteriser(ClassImposteriser.INSTANCE); 改變其中的Imposteriser才能做到。

原本對於細節實作還挺有興趣的,但無奈功力不夠,追了一些source就追不下去了0rz...只能大約知道有使用reflection機制去實作。
看來真的要開始培養自己鑽研open source的能力了...................


2013年3月3日 星期日

Android - Menu(1)(純顯示)


Android的Menu就是按下手機下方功能鍵會出現選單(至少我的XperiaP是按右下方)

實現的方式很簡單,共有兩種:

1.XML

(1)在 res/menu/下產生描述menu的選單介面,這裡我們使用gp_main_menu_option.xml
(2)加入以下的XML內容

    
    
    
    

其中的menuOption1與menuOption2都是對應的menuBtn ID,以及設置好預設的title
(3)在欲顯示Activity的Class中override functions:onCreateOptionsMenu、
 
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
     MenuInflater inflater = getMenuInflater();
     inflater.inflate(R.menu.gp_main_menu_option, menu);
     return super.onPrepareOptionsMenu(menu);
}




2.hard code

在欲顯示Activity的Class中override functions:onCreateOptionsMenu、
 
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
     super.onCreateOptionsMenu(menu);
     menu.add(0, 1, 0, "t1");
     menu.add(0, 2, 0, "t2");
     return true;
}

 


話說這些HTML編輯器的自動數字【編號清單】功能還真是有點陽春阿......這篇要貼XML內容只好不使用了,懶得另外改HTML

Eclipse Android Project Import From SVN


最近開始嘗試寫Android,但剛剛發現已經上傳到SVN的專案要checkOut到Eclipse卻一直失敗,直接使用Import->Projects From SVN弄下來的專案路徑整個是錯誤的,也無法自動產生gen/R.java

找了好久才找到個比較好用的方式,不知道是我使用svn checkout的方式錯誤還是SVN本身的問題(網路上也有看到有人有同樣問題)....

1.先使用TortoiseSVN依照一般方式將專案CheckOut出來
   建好資料夾->右鍵->SVN CheckOut
2.至Eclipse->Import->Existing Android Cod Into Workspace
3.Root Directory中選擇好步驟1 CheckOut的資料夾與Project
4.Next或Finish 完成


後來才發現不是只有AndroidProject有這Import問題,似乎所有Projects都有這種問題...= =