Introduction
Hello World
Project Structure
Data Layer
Data Source
Service Layer
Web Layer
GET Single Bank
Tutorial 01 Introduction Introduction Video: https://youtu.be/TJcshrJOnsE?list=PL6gx4Cwl9DGDPsneZWaOFg0H2wsundyGr
Create Project
Spring Initializr:
Project: Gradle
Language: Kotlin
Spring Boot: 2.5.0 (SNAPSHOT)
Project Metadata
Group tv.codealong.tutorials.springboot
Artifact thenewboston
Name thenewboston
Description Spring Boot Tutorial Series for TNB
Package name tv.codealong.tutorials.springboot.thenewboston
Packaging: Jar
Java 11
Dependences:
Tutorial 02 Hello World Video: https://youtu.be/PqNgTV9enbE?list=PL6gx4Cwl9DGDPsneZWaOFg0H2wsundyGr
Hello World touch src/main/resources/static/index.html
<h1 > Hello Spring Boot</h1 >
Run
this project in IntelliJ IDEA, and access http://127.0.0.1:8080 in Browers.
Create a REST Controller touch src/main/kotlin/tv/codealong/tutorials/springboot/thenewboston/HelloWorldController.kt
package tv.codealong.tutorials.springboot.thenewbostonimport org.springframework.web.bind.annotation .GetMappingimport org.springframework.web.bind.annotation .RequestMappingimport org.springframework.web.bind.annotation .RestController@RestController @RequestMapping("api/hello" ) class HelloWorldController { @GetMapping fun helloWorld () : String { return "Hello, this is a REST endpoint!" } }
Access: http://127.0.0.1:8080/api/hello
Tutorial 3 Project Structure Video: https://youtu.be/j5G4QZy0kZk?list=PL6gx4Cwl9DGDPsneZWaOFg0H2wsundyGr
Three files:
build.gradle.kts
settings.gradle.kts
gradle/wrapper/gradle-wrapper.properties
gradle-wrapper.properties
Gradle Version in: gradle/wrapper/gradle-wrapper.properties
distributionBase =GRADLE_USER_HOME distributionPath =wrapper/dists distributionUrl =https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip zipStoreBase =GRADLE_USER_HOME zipStorePath =wrapper/dists
./gradlew -v
./gradlew clean
./gradlew build
spring-boot-thenewboston > ./gradlew -v ------------------------------------------------------------ Gradle 6.8 .3 ------------------------------------------------------------ Build time: 2021 -02 -22 16 :13 :28 UTC Revision: 9 e26b4a9ebb910eaa1b8da8ff8575e514bc61c78 Kotlin: 1.4 .20 Groovy: 2.5 .12 Ant : Apache Ant (TM) version 1.10 .9 compiled on September 27 2020 JVM: 11.0 .7 (Oracle Corporation 11.0 .7 +8 -LTS) OS: Mac OS X 10.15 .7 x86_64
spring-boot-thenewboston > ./gradlew clean BUILD SUCCESSFUL in 1 s 1 actionable task : 1 executed
spring-boot-thenewboston > ./gradlew build BUILD SUCCESSFUL in 16 s 8 actionable tasks: 8 executed
Tutorial 4 Data Layer Video: https://youtu.be/1D1iL824ssk?list=PL6gx4Cwl9DGDPsneZWaOFg0H2wsundyGr
Api: https://thenewboston.com/bank-api/banks
touch src/main/kotlin/tv/codealong/tutorials/springboot/thenewboston/model/Bank.kt
package tv.codealong.tutorials.springboot.thenewboston.modeldata class Bank ( val accountNumber: String, val trust: Double , val transactionFee: Int )
Tutorial 5 Data Source Video: https://youtu.be/VVrKvpqAmw8?list=PL6gx4Cwl9DGDPsneZWaOFg0H2wsundyGr
touch src/main/kotlin/tv/codealong/tutorials/springboot/thenewboston/datasource/BankDataSource.kt
package tv.codealong.tutorials.springboot.thenewboston.datasourceimport tv.codealong.tutorials.springboot.thenewboston.model.Bankinterface BankDataSource { fun retrieveBanks () : Collection<Bank> }
touch src/main/kotlin/tv/codealong/tutorials/springboot/thenewboston/datasource/mock/MockBankDataSource.kt
package tv.codealong.tutorials.springboot.thenewboston.datasource.mockimport org.springframework.stereotype.Repositoryimport tv.codealong.tutorials.springboot.thenewboston.datasource.BankDataSourceimport tv.codealong.tutorials.springboot.thenewboston.model.Bank@Repository class MockBankDataSource : BankDataSource { val banks = listOf( Bank("aaa" , 2.0 , 1 ), Bank("bbb" , 3.0 , 2 ), Bank("ccc" , 4.0 , 3 ) ) override fun retrieveBanks () : Collection<Bank> = banks }
touch src/test/kotlin/tv/codealong/tutorials/springboot/thenewboston/datasource/mock/MockBankDataSourceTest.kt
package tv.codealong.tutorials.springboot.thenewboston.datasource.mockimport org.assertj.core.api.Assertions.assertThatimport org.junit.jupiter.api.Testinternal class MockBankDataSourceTest { private val mockDataSource: MockBankDataSource = MockBankDataSource() @Test fun `should provide a collection of banks`() { val banks = mockDataSource.retrieveBanks() assertThat(banks).isNotEmpty assertThat(banks.size).isGreaterThanOrEqualTo(3 ) } @Test fun `should provide some mock data `() { val banks = mockDataSource.retrieveBanks() assertThat(banks).allSatisfy { it.accountNumber.isNotBlank() } assertThat(banks).allMatch { it.accountNumber.isNotBlank() } assertThat(banks).anyMatch { it.trust != 0.0 } assertThat(banks).anyMatch { it.transactionFee != 0 } } }
Tutorial 6 Service Layer Video: https://youtu.be/Icnb3zvya-w?list=PL6gx4Cwl9DGDPsneZWaOFg0H2wsundyGr
Add testImplementation("io.mockk:mockk:1.10.4")
:
dependencies { # ... testImplementation("io.mockk:mockk:1.10.4" ) }
src/main/kotlin/tv/codealong/tutorials/springboot/thenewboston/service/BankService.kt
package tv.codealong.tutorials.springboot.thenewboston.serviceimport io.mockk.mockkimport io.mockk.verifyimport org.junit.jupiter.api.Testimport tv.codealong.tutorials.springboot.thenewboston.datasource.BankDataSourceinternal class BankServiceTest { private val dataSource: BankDataSource = mockk(relaxed = true ) private val bankService: BankService = BankService(dataSource) @Test fun `should call its data source to retrieve banks`() { val banks = bankService.getBanks() verify(exactly = 1 ) { dataSource.retrieveBanks() } } }
src/test/kotlin/tv/codealong/tutorials/springboot/thenewboston/service/BankServiceTest.kt
package tv.codealong.tutorials.springboot.thenewboston.datasource.mockimport org.assertj.core.api.Assertions.assertThatimport org.junit.jupiter.api.Testinternal class MockBankDataSourceTest { private val mockDataSource: MockBankDataSource = MockBankDataSource() @Test fun `should provide a collection of banks`() { val banks = mockDataSource.retrieveBanks() assertThat(banks).isNotEmpty assertThat(banks.size).isGreaterThanOrEqualTo(3 ) } @Test fun `should provide some mock data `() { val banks = mockDataSource.retrieveBanks() assertThat(banks).allSatisfy { it.accountNumber.isNotBlank() } assertThat(banks).allMatch { it.accountNumber.isNotBlank() } assertThat(banks).anyMatch { it.trust != 0.0 } assertThat(banks).anyMatch { it.transactionFee != 0 } } }
Tutorial 7 Web Layer Video: https://youtu.be/2e72RHO8ORk?list=PL6gx4Cwl9DGDPsneZWaOFg0H2wsundyGr
Access to http://127.0.0.1:8080/api/banks
[ { "accountNumber" : "aaa" ,"trust" : 2 ,"transactionFee" : 1 }, { "accountNumber" : "bbb" ,"trust" : 3 ,"transactionFee" : 2 }, { "accountNumber" : "ccc" ,"trust" : 4 ,"transactionFee" : 3 } ]
Tutorial 8 GET Single Bank Video: https://youtu.be/jiv37i503v4?list=PL6gx4Cwl9DGDPsneZWaOFg0H2wsundyGr