Skip to content

Commit

Permalink
doc update
Browse files Browse the repository at this point in the history
  • Loading branch information
arnaudgiuliani committed Feb 24, 2020
1 parent 024b7fe commit deed4db
Show file tree
Hide file tree
Showing 10 changed files with 284 additions and 82 deletions.
2 changes: 1 addition & 1 deletion koin-projects/docs/reference/koin-core/dsl.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ To describe your content in a module, you can use the following functions:
* `scope { // scope group }` - define a logical group for `scoped` definition
* `scoped { //definition }`- provide a bean definition that will exists only in a scope

Note: the `named()` function allow you to give a qualifier either by a string or a type. It is used to name your definitions.
Note: the `named()` function allow you to give a qualifier either by a string, an enum or a type. It is used to name your definitions.

### Writing a module

Expand Down
6 changes: 3 additions & 3 deletions koin-projects/docs/reference/koin-core/scopes.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ module {
}
```

> A scope require a _qualifier_ to help name it. It can be eitehr a String Qualifier, either a TypeQualifier
> A scope require a _qualifier_ to help name it. It can be either a String Qualifier, either a TypeQualifier
Declaring a scope for a given type, can be done:

Expand Down Expand Up @@ -62,11 +62,11 @@ class C

### Declare a Scoped Instance

Let's scope `B` & `C` instances from `A`, `B` & `C` instanceds are tied to a `A` instance:
Let's scope `B` & `C` instances from `A`, `B` & `C` instances are tied to a `A` instance:

```kotlin
module {
single { A() }
factory { A() }
scope<A> {
scoped { B() }
scoped { C() }
Expand Down
52 changes: 52 additions & 0 deletions koin-projects/docs/reference/koin-test/checkmodules_plugin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@

## Checking your modules with Koin Gradle Plugin

The Koin gradle plugin allow you to run `checkModules` task to run your modules verification.

### Gradle plugin

First, setup the Gradle plugin:

```groovy
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "org.koin:koin-gradle-plugin:$koin_version"
}
}
apply plugin: 'koin'
```

### The JUnit CheckModules test

You need to add a JUnit catgeory to let us run your checkModules tests: `@Category(CheckModuleTest::class)`

Each of the module test will use the `checkModules` API to check the module:

```kotlin
@Category(CheckModuleTest::class)
class CheckModulesTest : KoinTest {

@Test
fun checkAllModules() = checkModules {
modules(appModule)
}
}
```

### Verify your modules

Once done, you can verify your modules:

```
./gradlew checkModules
```

You can also verify your modules in a continuous way:

```
./gradlew checkModules --continuous
```
85 changes: 55 additions & 30 deletions koin-projects/docs/reference/koin-test/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
By tagging your class `KoinTest`, your class become a `KoinComponent` and bring you:

* `by inject()` & `get()` - function to retrieve yoru instances from Koin
* `check` & `dryRun` - help you check your configuration
* `checkModules` - help you check your configuration
* `declareMock` & `declare` - to declare a mock or a new definition in the current context

```kotlin
Expand Down Expand Up @@ -36,28 +36,67 @@ class MyTest : KoinTest {

?> Don't hesitate to overload Koin modules configuration to help you partly build your app.
## JUnit Rules
### Create a Koin context for your test
You can easily create and hold a Koin context for each of your test with the following rule:
```kotlin
@get:Rule
val koinTestRule = KoinTestRule.create {
// Your KoinApplication instance here
modules(myModule)
}
```
### Specify your Mock Provider
To let you use the `declareMock` API, you need to specify a rule to let Koin know how you build your Mock instance. This let you choose the right
mocking framework for your need. Below is a Mockito example:
```kotlin
@get:Rule
val mockProvider = MockProviderRule.create { clazz ->
// Your way to build a Mock here
Mockito.mock(clazz.java)
}
```
!> koin-test project is not tied anymroe to mockito
## Mocking out of the box
Instead of making a new module each time you need a mock, you can declare a mock on the fly with `declareMock`:
```kotlin
class ComponentA
class ComponentB(val a: ComponentA)
class MyTest : KoinTest {
class ComponentA
class ComponentB(val a: ComponentA)
@get:Rule
val koinTestRule = KoinTestRule.create {
modules(
module {
single { ComponentA() }
single { ComponentB(get()) }
})
}
@get:Rule
val mockProvider = MockProviderRule.create { clazz ->
Mockito.mock(clazz.java)
}
@Test
fun `should inject my components`() {
startKoin{
modules(
module {
single { ComponentA() }
single { ComponentB(get()) }
})
}
declareMock<ComponentA>()
}
// Replace current definition by a Mock
val mock = declareMock<ComponentA>()
// retrieve mock
// retrieve mock, same as variable above
assertNotNull(get<ComponentA>())
// is built with mocked ComponentA
Expand All @@ -84,30 +123,16 @@ When a mock is not enough and don't want to create a module just for this, you c
}
```

## Checking your Koin configuration
## Checking your Koin modules

Koin offers a way to test if you Koin modules are good: `checkModules` - walk through your definition tree and check if each definition is bound

```kotlin
@Test
fun `check MVP hierarchy`() {
startKoin{
modules(
module {
single { ComponentA() }
single { ComponentB(get()) }
})
}.checkModules()

// or

koinApplication{
modules(
module {
single { ComponentA() }
single { ComponentB(get()) }
})
}.checkModules()
checkModules {
modules(myModule1, myModule2 ...)
}
}
```

Expand Down
20 changes: 16 additions & 4 deletions koin-projects/docs/reference/setup/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@ Here are the current versions of Koin:

```groovy
// Current stable version
koin_version= "2.0.1"
// Latest unstable version
koin_version= "2.1.0-beta-1"
koin_version= "2.1.0"
```

### Gradle dependencies
Expand Down Expand Up @@ -40,6 +37,21 @@ implementation "org.koin:koin-core-ext:$koin_version"
testImplementation "org.koin:koin-test:$koin_version"
```

#### **Gradle Plugin**

```groovy
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "org.koin:koin-gradle-plugin:$koin_version"
}
}
apply plugin: 'koin'
```

#### **Android**

```groovy
Expand Down
1 change: 1 addition & 0 deletions koin-projects/docs/reference/sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
- [Experimental Features](koin-core/experimental)
- **Koin Test**
- [JUnit & Mocks](koin-test/testing)
- [CheckModules gradle Plugin](koin-test/checkmodules_plugin)
- **Koin Android**
- [Start on Android](koin-android/start)
- [Android DSL](koin-android/dsl)
Expand Down
12 changes: 11 additions & 1 deletion koin-projects/docs/start/getting-started/modules-definitions.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ val myModule = module {
}
```

> This qualifier can be associated to a Enum class or directly to a type:
```kotlin
// Type qualifier
single(named<MyClass>()) { MockDataRepository() }

// Enum qualifier
single(named<MyEnum.MyValue>()) { MockDataRepository() }
```

## Additional types

In the module DSL, for a definition, you can give some extra type to bind, with the `bind` operator (`binds` for list of KClass):
Expand Down Expand Up @@ -158,7 +168,7 @@ A quick recap of the Koin DSL keywords:
* `factory { }` - provide a *factory* bean definition
* `single { }` - provide a bean definition
* `get()` - resolve a component dependency
* `named()` - define a qualifier with type or string
* `named()` - define a qualifier with type, enum or string
* `bind` - additional Kotlin type binding for given bean definition
* `binds` - list of additional Kotlin types binding for given bean definition
* `getProperty()` - resolve a Koin property
Expand Down
75 changes: 66 additions & 9 deletions koin-projects/docs/start/getting-started/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,36 +36,93 @@ class MyTest : KoinTest {
}
```

## Checking your modules

You can check if your modules are good (all definitions are bounded) with the `checkModules` function on your `KoinApplication` instance:
you can use the `KoinTestRule` JUnit rule to statr/stop your Koin context:

```kotlin
class MyTest : KoinTest {


@get:Rule
val koinTestRule = KoinTestRule.create {
modules(appModule)
}

// Lazy inject property
val componentA : ComponentA by inject()

// use it in your tests :)
@Test
fun `checking modules`() {
// use koinApplication instead of startKoin, to avoid having to close Koin after each test
koinApplication { modules(appModule) }.checkModules()
fun `make a test with Koin`() {
// use componentA here!
}
}
```

## Checking your modules

We can use the Koin gradle plugin to let us run our module checks:

```gradle
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "org.koin:koin-gradle-plugin:$koin_version"
}
}
apply plugin: 'koin'
```

Let's write our check test as follow:
- using a JUnit `CheckModuleTest` category
- test modules with `checkModules { }` API

```kotlin
@Category(CheckModuleTest::class)
class ModuleCheckTest : AutoCloseKoinTest() {

@Test
fun checkModules() = checkModules {
modules(appModule)
}
}
```

Let's check our modules via Gradle command:

```
./gradlew checkModules
```

or

```
./gradlew checkModules --continuous
```

## Mocking on the fly

Once you have tagged your class with `KoinTest` interface, you can use the `declareMock` function to declare mocks & behavior on the fly:

```kotlin
class MyTest : KoinTest {

@get:Rule
val koinTestRule = KoinTestRule.create {
modules(appModule)
}

// required to make your Mock via Koin
@get:Rule
val mockProvider = MockProviderRule.create { clazz ->
Mockito.mock(clazz.java)
}

val componentA : ComponentA by inject()

@Test
fun `declareMock with KoinTest`() {
startKoin { modules(appModule) }

declareMock<ComponentA> {
// do your given behavior here
given(this.sayHello()).willReturn("Hello mock")
Expand Down
Loading

0 comments on commit deed4db

Please sign in to comment.