Пытаюсь понять котлин Д.И. в Spring boot, вообще - PullRequest
0 голосов
/ 16 мая 2019

почему-то у меня все еще есть огромные проблемы с захватом DI стиля kotlin при весенней загрузке Особенно в тестах JUnit.

@RunWith(SpringJUnit4ClassRunner::class)
@SpringBootTest(classes = [(ApplicationConfig::class)])
class DataServiceTest {

private var dataService: DataService
private var addressRepository: AddressRepository

@Test
fun shouldUpdateCustomerEmail() {

    dataService.setNewCustomerEmail("1212", ApiEmail("test@test.org"))

  }
}

Это очень простой тест, который у меня есть. Я пробовал несколько стилей инъекций.

private var dataService: DataService

Ошибка: свойство должно быть инициализировано (имеет смысл)

private lateinit var dataService: DataService

Ошибка: свойство данных lateinit не было инициализировано (да, я его не инициализировал)

@Autowired
private lateinit var dataService: DataService

Ошибка: не найдены bean-компоненты типа 'DataService' (почему? В других сервисах нормально)

class DataServiceTest @Autowired constructor(
        private val dataService: DataService
) { ... }

Ошибка: не найдены bean-компоненты типа 'DataService' (почему? В других сервисах нормально)

private var dataService: DataService = DataService()

Не выдает ошибки.

, но не может использовать тот же стиль для внедрения хранилища интерфейса для адресов, поскольку нет конструктора для интерфейса , поэтому хранилище будет неинициализировано и снова выдаст ошибку внутри setNewCustomerEmail()

DataService является классом @Service с одним методом (на данный момент) и отлично работает при вызове из состояния покоя, но аварийно завершается при вызове из @Test

@Service
class DataService { 

    @Autowired
    private lateinit var addressRepository: AddressRepository

    fun setNewCustomerEmail(id: String, email: ApiEmail) {
        val addressList = addressRepository.findAddressById( id.toInt() )
        ...
    }
 }

Я понимаю, почему возникает большая часть этих ошибок, но кажется, что есть много способов для DI определить другие зависимости (классы и переменные) в kotlin + spring boot, но, похоже, для каждого варианта использования он будет разным, что хорошо, но я не могу понять, когда что использовать.

Как мне понять Kotlin DI?

Как правильно добавить этот интерфейс хранилища?

Я уже читал:

Как использовать весенние аннотации, такие как @Autowired в kotlin?

https://www.bignerdranch.com/blog/kotlin-when-to-use-lazy-or-lateinit/

EDIT Кроме того * +1048 *

https://spring.io/guides/tutorials/spring-boot-kotlin/

Показывает следующий код:

interface UserRepository : CrudRepository<User, Long> {
  fun findByLogin(login: String): User
}

и затем:

@DataJpaTest
class RepositoriesTests @Autowired constructor(
    val entityManager: TestEntityManager,
    val userRepository: UserRepository,
    val articleRepository: ArticleRepository) { ... }

Это именно то, что я пытаюсь сделать здесь ... но если я попытаюсь сделать конструктор @Autowire с DataService, я получу ошибку: не найдены компоненты типа DataService.

class DataServiceTest @Autowired constructor(
        val dataService: DataService
) ... no beans of type 'DataService' found

И если я попытаюсь использовать AddressRepository в качестве параметра конструктора в DataService, я теперь должен передать репозиторий или использовать @Bean, ни тот, который у меня есть?

class DataService @Autowired constructor(
        private val AddressRepository: AddressRepository
)

Я ооочень смущен этим ....

1 Ответ

0 голосов
/ 19 мая 2019

Я бы порекомендовал использовать инжектор конструктора для определения всех зависимостей для вашего сервиса:

@Service
class DataService(private val addressRepository: AddressRepository) {
   fun setNewCustomerEmail() {...}
}

Обратите внимание, что вы можете опустить @Autowired здесь.

Чтобы проверить, что вы можете использовать простой модульный тест и настроить объект самостоятельно:

class DataServiceTest {
   val mock    = mock<AddressRepository>() // e.g. Mockito
   val service = DataService(mock)

   @Test
   fun myTest() {
     ...
   }
}

В качестве альтернативы вы можете использовать SpringRunner для написания интеграционного теста. Spring будет обрабатывать создание и внедрение вашего сервиса и репозитория.

@RunWith(SpringRunner::class)
@SpringBootTest
class DataServiceTest {
   @Autowired
   lateinit var dataService: DataService
}

Поскольку вы, похоже, используете JUnit4 AFAIK, невозможно использовать инжектор конструктора. Для этого вам нужно использовать комбо @ Autowired / lateinit. При использовании JUnit5 должна быть возможность определить дополнительный конструктор в вашем тестовом классе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...