Skip to content

Commit

Permalink
add junit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
xcodeassociated committed Sep 16, 2024
1 parent 4608498 commit 9a490ba
Show file tree
Hide file tree
Showing 8 changed files with 246 additions and 75 deletions.
8 changes: 8 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ dependencies {
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
testImplementation 'org.springframework.boot:spring-boot-starter-test'

// test utils
testImplementation 'io.projectreactor:reactor-test'
testImplementation 'io.mockk:mockk:1.13.12'
testImplementation 'com.ninja-squad:springmockk:4.0.2'

// wiremock
testImplementation 'org.wiremock:wiremock-standalone:3.9.1'

// monitoring
runtimeOnly 'io.micrometer:micrometer-registry-prometheus'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import org.apache.commons.logging.LogFactory
import org.springframework.context.ApplicationEventPublisher
import org.springframework.data.domain.Page
import org.springframework.http.ResponseEntity
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
Expand All @@ -18,6 +19,7 @@ import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController

@RestController
@Validated
class PermissionController(
private val permissionService: PermissionService,
private val applicationEventPublisher: ApplicationEventPublisher
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ package com.softeno.template.sample.http.external.api
import com.softeno.template.sample.http.external.client.ExternalServiceClient
import org.apache.commons.logging.LogFactory
import org.springframework.http.ResponseEntity
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/external")
@Validated
class ExternalController(
private val externalServiceClient: ExternalServiceClient
) {
Expand Down

This file was deleted.

216 changes: 216 additions & 0 deletions src/test/kotlin/com/softeno/template/app/IntegrationTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
package com.softeno.template.app

import com.github.tomakehurst.wiremock.WireMockServer
import com.github.tomakehurst.wiremock.client.WireMock.*
import com.github.tomakehurst.wiremock.client.WireMock.aResponse
import com.github.tomakehurst.wiremock.client.WireMock.urlMatching
import com.github.tomakehurst.wiremock.core.WireMockConfiguration.options
import com.ninjasquad.springmockk.MockkBean
import com.softeno.template.SoftenoMvcJpaApp
import com.softeno.template.app.permission.PermissionFixture.Companion.aPermission
import com.softeno.template.app.permission.PermissionFixture.Companion.aPermissionDto
import com.softeno.template.app.permission.db.PermissionRepository
import io.mockk.every
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.context.properties.ConfigurationPropertiesScan
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.core.Ordered
import org.springframework.core.annotation.Order
import org.springframework.data.domain.PageImpl
import org.springframework.data.domain.Pageable
import org.springframework.kafka.test.context.EmbeddedKafka
import org.springframework.test.web.reactive.server.WebTestClient
import org.springframework.web.reactive.function.BodyInserters
import org.springframework.web.reactive.function.client.WebClient
import org.testcontainers.containers.PostgreSQLContainer
import org.testcontainers.junit.jupiter.Container
import org.testcontainers.junit.jupiter.Testcontainers

@Testcontainers
@SpringBootTest(
classes = [SoftenoMvcJpaApp::class],
properties = ["spring.profiles.active=integration"],
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
)
@AutoConfigureWebTestClient(timeout = "6000")
@EnableConfigurationProperties
@EmbeddedKafka(partitions = 1, brokerProperties = ["listeners=PLAINTEXT://localhost:9092", "port=9092"])
@ConfigurationPropertiesScan("com.softeno")
abstract class BaseIntegrationTest {

@Autowired
lateinit var permissionRepository: PermissionRepository

@Autowired
lateinit var webTestClient: WebTestClient

@Container
var postgreSQLContainer = PostgreSQLContainer("postgres:15.2-alpine")
.withDatabaseName("application")
.withUsername("admin")
.withPassword("admin")


@BeforeEach
fun init() {
// ...
}

@AfterEach
fun cleanup() {
permissionRepository.deleteAll()
}

}

class ContextLoadsTest : BaseIntegrationTest() {

@Test
fun testConnection() {
assertTrue(postgreSQLContainer.isRunning)
}
}

class PermissionTest : BaseIntegrationTest() {

@Test
fun shouldReturnEmptyPermissionResponse() {
webTestClient.get().uri("/permissions")
.exchange()
.expectStatus().isOk()
.expectBody().jsonPath("content").isEmpty
}

@Test
fun shouldRetrievePermission() {
val aPermission = aPermission()
permissionRepository.save(aPermission)

webTestClient.get().uri("/permissions")
.exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath("content.[0].name").isEqualTo(aPermission.name!!)
.jsonPath("content.[0].description").isEqualTo(aPermission.description!!)
}

@Test
fun shouldPersistPermission() {
val aPermissionDto = aPermissionDto()

webTestClient.post().uri("/permissions")
.body(BodyInserters.fromValue(aPermissionDto))
.exchange()
.expectStatus().isOk

assertEquals(permissionRepository.findAll().size, 1)
assertEquals(permissionRepository.findAll()[0].name!!, aPermissionDto.name)
assertEquals(permissionRepository.findAll()[0].description!!, aPermissionDto.description)
}
}

class PermissionTestMockk : BaseIntegrationTest() {

@MockkBean
@Order(value = Ordered.HIGHEST_PRECEDENCE)
lateinit var permissionRepositoryMock: PermissionRepository

@BeforeEach
fun initMockkRepository() {
every { permissionRepositoryMock.deleteAll() }.answers { }
}

@Test
fun shouldPersistAndRetrievePermission() {
val aPermission = aPermission()

every { permissionRepositoryMock.findAll(any<Pageable>()) }.answers { PageImpl(listOf(aPermission)) }

webTestClient.get().uri("/permissions")
.exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath("content.[0].name").isEqualTo(aPermission.name!!)
.jsonPath("content.[0].description").isEqualTo(aPermission.description!!)
}
}

data class SampleResponseDto(val data: String)

class ExternalControllerTest : BaseIntegrationTest(), ExternalApiAbility {

@Autowired
private lateinit var webclient: WebClient

private val wiremock: WireMockServer = WireMockServer(options().port(4500))

@BeforeEach
fun `setup wiremock`() {
wiremock.start()
}

@AfterEach
fun `stop wiremock`() {
wiremock.stop()
wiremock.resetAll()
}

@Test
fun `mock external service with wiremock`() {
// given
mockGetId(wiremock)

val expected = SampleResponseDto(data = "1")

// expect
val response = webclient.get().uri("http://localhost:4500/sample/100")
.retrieve()
.bodyToMono(SampleResponseDto::class.java)
.block()

assertEquals(expected, response)
}

@Test
fun `test external controller`() {
// given
mockGetId(wiremock)

// expect
webTestClient.get().uri("/external/1")
.exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath("data").isEqualTo("1")
}
}

interface ExternalApiAbility {

fun mockGetId(wiremock: WireMockServer) {
wiremock.stubFor(
get(urlMatching("/sample/.*"))
.willReturn(
aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody(
"""
{
"data": "1"
}
""".trimIndent()
)
)
)
}
}


This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,23 @@ import com.softeno.template.app.permission.mapper.PermissionDto
class PermissionFixture {
companion object {
@JvmStatic
fun somePermissionDto(name: String, description: String) = PermissionDto(name = name, description = description,
fun aPermission(name: String = "some permission", description: String = "some description"): Permission {
val permission = Permission()
permission.id = null
permission.createdDate = null
permission.createdBy = null
permission.modifiedBy = null
permission.modifiedDate = null
permission.version = null
permission.name = name
permission.description = description

return permission
}


@JvmStatic
fun aPermissionDto(name: String = "some permission", description: String = "some description") = PermissionDto(name = name, description = description,
id = null, version = null, createdBy = null, createdDate = null, modifiedBy = null, modifiedDate = null)
}
}
2 changes: 1 addition & 1 deletion src/test/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ spring.application.name=SoftenoJpaPostgresApp

### custom: external services

com.softeno.external.url=http://localhost:4500
com.softeno.external.url=http://localhost:4500/sample
com.softeno.external.name=node-service

com.softeno.kafka.tx=sample_topic_2
Expand Down

0 comments on commit 9a490ba

Please sign in to comment.