페이지 트리
메타 데이터의 끝으로 건너뛰기
메타 데이터의 시작으로 이동

support library(beta 버전, rc 버전)을 쓰면 Preview가 나오지 않는다.

현재 API 28 Pie가 새롭게 나오면서 support library도 맞춰서 버전을 내놓고 있다.

그래서 안드로이드 스튜디오를 통해 프로젝트를 만들면 build.gradle에 포함되는 support library가 beta, rc 버전일 때도 있다.

이럴경우 layout 파일에서 Preview 기능이 제대로 동작하지 않으니 다운그레이드를 해주어야 한다.

다운그레이드 할 때는 compileSdkVersion, targetSdkVersion을 같이 내려줘야 한다.

build.gradle
android {
    // compileSdkVersion 28
	compileSdkVersion 27

    defaultConfig {
        // targetSdkVersion 28
		targetSdkVersion 27
		// ....
    }
}

dependencies {
    // implementation 'com.android.support:appcompat-v7:28.0.0-beta01'
    implementation 'com.android.support:appcompat-v7:27.1.1'
}

위와 같이 바꾸고 다시 layout 파일로 가서 Preview 기능을 작동시켜보면 잘 작동한다.



디폴트 생성자 관련 에러

JPA, Jackson, Gson, Retrofit, AAC Room 등등 디폴트 생성자가 필요한 모든 곳에서 다양한 Exception을 던져준다.

코틀린은 기본적으로 모든 매개변수에 초기값을 지정해 주지 않으면 매개변수가 하나도 없는 디폴트 생성자는 생성되지 않는다.

아래는 Jackson 라이브러리를 통해 역직렬화를 할 때 받은 에러다.


에러
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.github.galcyurio.fakeapi.data.Post` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)


해결방법은 모든 매개변수에 초기값을 주던가 No-arg compiler plugin 을 적용하면 된다.

안드로이드라면 플러그인을 아래처럼 적용하면 된다.

  1. project 수준의 build.gradle 에 플러그인을 추가한다.

    build.gradle
    buildscript {
        dependencies {
            classpath "org.jetbrains.kotlin:kotlin-noarg:$kotlin_version"
        }
    }



  2. app 수준의 build.gradle 에 플러그인을 적용한다.

    build.gradle
    apply plugin: "kotlin-noarg"
  3. 디폴트 생성자를 생성해줄 어노테이션을 하나 만든다. 이미 쓰이고 있는게 있다면 생략해도 된다.

    package net.slipp.commons
    
    
    annotation class NoArgsConstructor
  4. 해당 어노테이션을 app 수준의 build.gradle 에 등록해준다.

    build.gradle
    noArg {
        annotation("net.slipp.commons.NoArgsConstructor")
    }
  5. 디폴트 생성자가 필요한 곳에 어노테이션을 달아준다.


JPA와 같은 경우는 플러그인을 등록할 때 apply plugin: "kotlin-jpa" 로 해주면  @Entity@Embeddable@MappedSuperclass 가 자동으로 등록이 되어서 noArg 블럭에 등록해줄 필요가 없다.


Mockito로 mocking할 시에 final 에러

코틀린은 클래스를 만들면 기본적으로 final 이기 때문에 따로 open 키워드를 명시해주지 않으면 Mockito로 mocking 할 시에 아래와 같은 에러를 준다.


org.mockito.exceptions.base.MockitoException:  
Cannot mock/spy class Utils  
Mockito cannot mock/spy following:  
  - final classes
  - anonymous classes
  - primitive types


이런 경우 명시적으로 open을 넣는 방법외에 두 가지 정도의 방법이 더 있다.

  1. open 키워드 추가
  2. Mockito2 사용
  3. Kotlin all-open compiler plugin 사용

추천하는 방법은 안드로이드일 경우에는 2번, 스프링 + 코틀린 조합일 경우에는 2번, 3번이다.


Mockito2 사용하기

Mockito2 부터는 final class에 대한 mocking도 제대로 지원한다.

다만 아래의 경로에 파일을 하나 추가해주어야 한다.


src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker

org.mockito.plugins.MockMaker
mock-maker-inline

위와 같이 test/resources 디렉토리 쪽에 파일을 하나 추가해주고 난 뒤에 mocking을 시도해보면 정상적으로 작동한다.

All-open compiler plugin 사용하기

해당 방법을 사용하면 open 키워드 대신에 어노테이션을 붙여서 open되도록 만들 수있다.

buildscript {
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version"
    }
}

apply plugin: "kotlin-allopen"
// apply plugin: "kotlin-spring"


allOpen {
    annotation("net.slipp.misc.Open")
    // annotations("com.another.Annotation", "com.third.Annotation")
}
package net.slipp.misc


@Retention(AnnotationRetention.SOURCE)
@Target(AnnotationTarget.CLASS)
annotation class Open


위와 같이 빌드 파일에 설정해두고 open 키워드를 쓰지 않고 open 해주고 싶은 클래스에 @Open 을 달아주면 된다.

만약 스프링 프레임워크를 쓰고 있다면 apply plugin: "kotlin-allopen"을 지우고 apply plugin: "kotlin-spring" 을 써주면 된다.

이렇게 하면 따로 Open annotation class 를 만들 필요없이 스프링의 @Controller, @Service, @Configuration 와 같은 어노테이션이 자동으로 등록되어 open 된다.

Maven을 쓰는 경우는 여기를 참조하자.


  • 레이블 없음