1. 程式人生 > >Greendao 自動生成單元測試

Greendao 自動生成單元測試

單元測試無疑是個好東西,不然每次都要去編譯整個專案然後安裝到模擬器啟動,按照指定的步驟去看是否有問題,這樣非常浪費時間,之前公司的專案超過10萬行,每次編譯都在3.5分鐘左右,遇到需要除錯的地方更加花時間。所以決定花時間研究下單元測試。先從資料庫開始吧。 

1.專案中引入greendao 進行簡單的配置

android {
    compileSdkVersion rootProject.ext.android.compileSdkVersion
    defaultConfig {
        minSdkVersion rootProject.ext.android.minSdkVersion
        targetSdkVersion rootProject.ext.android.targetSdkVersion
        versionCode 1
        versionName "1.0"
    }
    //greendao配置
    greendao {
        //版本號,升級時可配置
        schemaVersion 1
        //greendao 根目錄
        targetGenDir 'src/main/java/'
        //單元測試的根目錄
        targetGenDirTests 'src/main/java/'
        //生成的檔案的包名
        daoPackage 'greendao'
        //自動生成單元測試
        generateTests true
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    testOptions {
        unitTests.returnDefaultValues = true
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    lintOptions {
        abortOnError false
    }
    publishNonDefault true
}

其他配置可以忽略。

然後寫一個實體類

@Entity(nameInDb = "test")
public class TestDb {
    @Id
    @Property(nameInDb = "_id")
    private Long id;

    @Property(nameInDb = "name")
    private String name;

    @Generated(hash = )
    public TestDb(Long id, String name) {
        this.id = id;
        this.name = name;
    }

    @Generated(hash = )
    public TestDb() {
    }

    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "TestDb{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

build----》makeProject 完成之後就會自動生成

看看自動生成的

package greendao;

import org.greenrobot.greendao.test.AbstractDaoTestLongPk;
import greendao.TestDbDao;

public class TestDbTest extends AbstractDaoTestLongPk<TestDbDao, TestDb> {

    public TestDbTest() {
        super(TestDbDao.class);
    }

    @Override
    protected TestDb createEntity(Long key) {
        TestDb entity = new TestDb();
        entity.setId(key);
        return entity;
    }

}

 右鍵執行報錯:

java.lang.RuntimeException: Could not prepare DAO Test

	at org.greenrobot.greendao.test.AbstractDaoTest.setUp(AbstractDaoTest.java:71)
	at org.greenrobot.greendao.test.AbstractDaoTestSinglePk.setUp(AbstractDaoTestSinglePk.java:52)
	at junit.framework.TestCase.runBare(TestCase.java:139)
	at junit.framework.TestResult$1.protect(TestResult.java:122)
	at junit.framework.TestResult.runProtected(TestResult.java:142)
	at junit.framework.TestResult.run(TestResult.java:125)
	at junit.framework.TestCase.run(TestCase.java:129)
	at junit.framework.TestSuite.runTest(TestSuite.java:252)
	at junit.framework.TestSuite.run(TestSuite.java:247)
	at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:86)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)
Caused by: java.lang.reflect.InvocationTargetException
	at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.greenrobot.greendao.test.AbstractDaoTest.setUpTableForDao(AbstractDaoTest.java:78)
	at org.greenrobot.greendao.test.AbstractDaoTest.setUp(AbstractDaoTest.java:67)
	... 19 more
Caused by: java.lang.NullPointerException
	at org.greenrobot.greendao.database.StandardDatabase.execSQL(StandardDatabase.java:37)
	at greendao.TestDbDao.createTable(TestDbDao.java:43)
	... 24 more

找了很久網上基本上沒給什麼有用的資訊:最後斷點的時候發現getcontext 是空的,導致建立的資料庫是空的。

這涉及到兩點:androidTest 和test 的區別問題,如果是純java 不需要android模擬器純java環境的就放在test 目錄下,如果需要模擬器提供android 環境相關功能就放在 androidtest 下面,暫時只看到這些。

回頭看看我們的配置:

這個很明顯不是androidTest目錄,那麼試著把它改成 androidTest 目錄

這個時候生成的檔案就在androidTest目錄下面了

點進去之後發現報紅

手動將包名改一下,之後執行就好了,但是難道每次都要去改包名嗎?

網上查到的修改 test路徑的方法

android { 
sourceSets { 
test.root 'src/tests/javaTest' 
test.java.srcDirs 'src/tests/javaTest/java'
 androidTest.root 'src/tests/androidTest' 
androidTest.java.srcDirs 'src/tests/androidTest/java' 
}
}

沒試過應該是可以的。

或者試著在daopackage 設定成專案的路徑

  greendao {
        //版本號,升級時可配置
        schemaVersion 1
        //greendao 根目錄
        targetGenDir 'src/main/java'
        //單元測試的根目錄
        targetGenDirTests 'src/androidTest/java'
        //生成的檔案的包名
        daoPackage '你的專案包名.greendao'注意這裡打點不是"/"
        //自動生成單元測試
        generateTests true
    }

右鍵執行正常

後續就可以在每個TestCase類裡面寫自己想要測試的邏輯了.

注意!!!

如果生成的test 不是在專案相同的目錄下

就是這個自動生成的test 所在的資料夾裡面 將不會成功,說會說class not found,

這個坑裡面爬了大半天了!!!終於出來了!!!