Как выполнить модульные тесты лямбда-обработчика AWS с Dagger2 и Kotlin? - PullRequest
0 голосов
/ 06 сентября 2018

У меня возникли проблемы при попытке выяснить, как писать модульные тесты для обработчика AWS Lambda. Вот пример:

App.kt - класс обработки лямбда-обработчиков AWS.

class App : RequestHandler<Any, Any> {
    private val component: AppComponent by lazy {
        DaggerAppComponent.create()
    }
    override fun handleRequest(input: Any, context: Context): Any {
        component.getBusinessLogic().doSomething()
        // code
    }
}

AppComponent.kt - это компонент Dagger2 для получения бизнес-логики.

@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {
    fun getBusinessLogic(): BusinessLogic
}

AppModule.kt - это модуль Dagger2.

@Module
abstract class AppModule {
    @Provides
    @Singleton
    fun provideAmazonECS(): AmazonECS = AmazonECSClient.builder().build()
}

BusinessLogic.kt - бизнес-логика лямбда-функции AWS

class BusinessLogic @Inject constructor(...) {
    fun doSomething(): Any{
        // code to use AmazonECS
    }
}

Теперь вот как я хотел бы проверить App.kt, посмеиваясь над классом BusinessLogic.

AppTest.kt

class AppTest {
    @Test
    fun `test something`() {
        val mockLogic = mock(BusinessLogic::class.java)
        val app = App()
        `when`(mockLogic.doSomething()).thenReturn(...)

        app.handleRequest(...)
    }
    @Test
    fun `test exception`() {
        val mockLogic = mock(BusinessLogic::class.java)
        val app = App()
        `when`(mockLogic.doSomething()).thenThrow(...)

        assertThrows<...> { app.handleRequest(...) }
    }
}

Итак, моя проблема в том, что я не уверен, как использовать поддельный экземпляр BusinessLogic. Класс App должен иметь пустой конструктор, чтобы AWS-лямбда мог создать его экземпляр. Изменение кода, такое как создание вторичного конструктора только для модульного тестирования, не подходит.

Заранее спасибо, и я благодарен за любую помощь в этом вопросе.

1 Ответ

0 голосов
/ 07 сентября 2018

Спасибо @Dominik G. за комментарии, и вот решение, основанное на разговоре.

App.kt изменен таким образом, чтобы в нем была только одна строка, и, таким образом, его не нужно проверять модулем.

class App : RequestHandler<Any, Any> {
    private val component: AppComponent by lazy {
        DaggerAppComponent.create()
    }
    override fun handleRequest(input: Any, context: Context): Any {
        return component.getLambdaLogic().handleRequest(input, context)
    }
}

LambdaLogic.kt теперь содержит логику специально для AWS лямбда.

class LambdaLogic @Inject constructor(businessLogic: BusinessLogic) {
    fun handleRequest(input: Any, context: Context): Any {
        businessLogic.doSomething()
        // code
    }
}

AppComponent.kt изменен так, чтобы возвращать LambdaLogic вместо BusinessLogic.

@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {
    fun getLambdaLogic(): LambdaLogic
}

LambdaLogicTest.kt проверяет лямбда-логику AWS.

class LambdaLogicTest{
    @Test
    fun `test something`() {
        val mockBusinessLogic = mock(BusinessLogic::class.java)
        val lambdaLogic = LambdaLogicTest(mockBusinessLogic)
        `when`(mockBusinessLogic.doSomething()).thenReturn(...)

        lambdaLogic.handleRequest(...)
    }
    @Test
    fun `test exception`() {
        val mockBusinessLogic = mock(BusinessLogic::class.java)
        val lambdaLogic = LambdaLogicTest(mockBusinessLogic)
        `when`(mockBusinessLogic .doSomething()).thenThrow(...)

        assertThrows<...> { lambdaLogic.handleRequest(...) }
    }
}

При использовании этого подхода больше не требуется модульное тестирование App.kt, и мы также можем проводить модульные тесты лямбда-логики AWS.

...