Skip to content

Commit

Permalink
TESTING PLAYING GOD
Browse files Browse the repository at this point in the history
  • Loading branch information
piotr.suwala committed Dec 21, 2023
1 parent 23da935 commit 8397a12
Show file tree
Hide file tree
Showing 10 changed files with 154 additions and 58 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@ Backend is available at [http://localhost:8080/](http://localhost:8080/)

## SWAGGER

http://localhost:8080/swagger-ui.html
### While docker composing

http://localhost:8000/swagger-ui.html
3 changes: 3 additions & 0 deletions backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:${coroutinesVersion}")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor:${coroutinesVersion}")

testImplementation "io.projectreactor:reactor-test"


implementation 'com.fasterxml.jackson.module:jackson-module-kotlin'
implementation 'org.axonframework:axon-spring-boot-starter'
implementation 'org.axonframework.extensions.kotlin:axon-kotlin'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import reactor.core.publisher.Flux
import reactor.core.publisher.toFlux
import java.time.Duration
import java.util.*
import kotlin.reflect.KClass
Expand All @@ -32,7 +33,7 @@ class OrganisationController(

@PostMapping
suspend fun create(user: Party.User, @RequestBody createOrganisationDTO: CreateOrganisationDTO) {
eventBus.awaitingEvent(UserToOrganisationsModelViewUpdated::class) { correlationId ->
eventBus.awaitingEvent(OrganisationCreated::class) { correlationId ->
createOrganisationDTO.let {
commandGateway.send<Unit>(
CreateOrganisation(it.name, user),
Expand All @@ -52,13 +53,17 @@ class OrganisationController(
.let { UserOrganisationViewModel(it) }

@GetMapping(path = ["/stream"], produces = [MediaType.TEXT_EVENT_STREAM_VALUE])
fun testServerSentEvents(user: Party.User): Flux<UserOrganisationViewModel> {
return Flux.interval(Duration.ofMillis(1000))
.map { UserOrganisationViewModel(listOf(
UserOrganisationsView(UUID.randomUUID(), "xD"),
UserOrganisationsView(UUID.randomUUID(), "xD2"),
)) }
}
fun testServerSentEvents(user: Party.User): Flux<UserOrganisationViewModel> =
queryGateway.subscriptionQuery(
QueryUserOrganisations(user),
ResponseTypes.multipleInstancesOf(UserOrganisationsView::class.java),
ResponseTypes.multipleInstancesOf(UserOrganisationsView::class.java)
).let {
Flux.concat(
it.initialResult().toFlux(),
it.updates()
).map { UserOrganisationViewModel(it) }
}
}

suspend fun EventBus.awaitingEvent(eventType: KClass<*>, block: suspend (correlationId: String) -> Unit) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import org.axonframework.eventhandling.DomainEventMessage
import org.axonframework.eventhandling.EventHandler
import org.axonframework.eventhandling.gateway.EventGateway
import org.axonframework.queryhandling.QueryHandler
import org.axonframework.queryhandling.QueryMessage
import org.axonframework.queryhandling.QueryUpdateEmitter
import org.springframework.data.repository.CrudRepository
import org.springframework.stereotype.Service
import java.io.Serializable
import java.util.*
import java.util.function.Predicate
import javax.persistence.Embeddable
import javax.persistence.EmbeddedId
import javax.persistence.Entity
Expand All @@ -23,19 +25,21 @@ class UserToOrganisationsEventProcessor(

@EventHandler(payloadType = MemberAdded::class)
fun handle(event: DomainEventMessage<MemberAdded>) {
val userId = event.payload.user.id;
val update =
repository.save(
UserToOrganisationsModel(
UserAndOrganisation(event.payload.user.id, UUID.fromString(event.aggregateIdentifier)),
event.payload.organisationName
)

repository.save(
update
)

eventGateway.publish(UserToOrganisationsModelViewUpdated())

queryUpdateEmitter.emit(QueryUserOrganisations::class.java, { query -> query.user.id == userId }, update)
queryUpdateEmitter.emit(
QueryUserOrganisations::class.java,
{ x -> x.user.partyId == event.payload.user.id },
repository.findAllByIdUserId(event.payload.user.id)
.map { UserOrganisationsView(it.id.associatedGroup, it.organisationName) }
)
}

@QueryHandler
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,12 @@
package com.ksidelta.libruch.modules.user

import org.axonframework.eventhandling.EventHandler
import org.springframework.data.repository.CrudRepository
import org.springframework.stereotype.Repository
import org.springframework.stereotype.Service
import java.io.Serializable
import java.util.*
import javax.persistence.Embeddable
import javax.persistence.EmbeddedId
import javax.persistence.Entity
import javax.persistence.IdClass

@Service
class UserEventHandler(val userModelRepository: UserModelRepository) {
@EventHandler
fun handleNewuser(userCreated: UserCreated) {
userCreated.run {
userModelRepository.save(
UserModel(
UserIdKey(id.type, id.userId),
assignedGlobalId,
username
)
)
}
}
}

@Repository
interface UserModelRepository : CrudRepository<UserModel, UserIdKey> {
Expand All @@ -35,6 +16,7 @@ interface UserModelRepository : CrudRepository<UserModel, UserIdKey> {
data class UserModel(
@EmbeddedId
val userId: UserIdKey,

val uuid: UUID,
val username: String
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package com.ksidelta.libruch.modules.user

import com.ksidelta.libruch.modules.organisation.awaitingEvent
import kotlinx.coroutines.runBlocking
import org.axonframework.commandhandling.gateway.CommandGateway
import org.axonframework.eventhandling.EventBus
import org.axonframework.messaging.MetaData
import org.springframework.http.HttpStatus
import org.springframework.orm.jpa.JpaSystemException
import org.springframework.retry.annotation.Backoff
Expand All @@ -21,7 +25,8 @@ interface UserService {
@Service
class UserServiceImpl(
val userModelRepository: UserModelRepository,
val commandGateway: CommandGateway
val commandGateway: CommandGateway,
val eventBus: EventBus
) : UserService {

@OptIn(ExperimentalStdlibApi::class)
Expand All @@ -30,6 +35,7 @@ class UserServiceImpl(
maxAttempts = 5,
backoff = Backoff(delay = 100, multiplier = 2.0)
)

@Transactional
override fun logUser(principal: Principal): UUID {

Expand All @@ -44,9 +50,10 @@ class UserServiceImpl(
if (userUUID == null) {
userUUID = UUID.randomUUID()

commandGateway.send<Unit>(
CreateUser(
ProviderTypeAndUserId(userId.type, userId.userId),
userModelRepository.save(
UserModel(
UserIdKey(userId.type, userId.userId),
userUUID,
userDetails.username
)
)
Expand Down
40 changes: 38 additions & 2 deletions backend/src/test/kotlin/com/ksidelta/libruch/BaseTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,18 @@ import com.ksidelta.libruch.modules.user.UserService
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.BeforeEach
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.test.web.client.TestRestTemplate
import org.springframework.boot.test.web.reactive.server.WebTestClientBuilderCustomizer
import org.springframework.boot.test.web.server.LocalServerPort
import org.springframework.boot.web.client.RestTemplateBuilder
import org.springframework.context.ApplicationContext
import org.springframework.context.annotation.AnnotationConfigApplicationContext
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Import
import org.springframework.context.annotation.Primary
import org.springframework.context.annotation.Scope
import org.springframework.context.event.ContextStoppedEvent
import org.springframework.context.event.EventListener
import org.springframework.core.MethodParameter
Expand All @@ -28,7 +34,9 @@ import org.springframework.stereotype.Component
import org.springframework.stereotype.Service
import org.springframework.test.context.DynamicPropertyRegistry
import org.springframework.test.context.DynamicPropertySource
import org.springframework.test.web.reactive.server.WebTestClient
import org.springframework.web.reactive.BindingContext
import org.springframework.web.reactive.function.client.WebClient
import org.springframework.web.reactive.result.method.HandlerMethodArgumentResolver
import org.springframework.web.server.ResponseStatusException
import org.springframework.web.server.ServerWebExchange
Expand All @@ -55,8 +63,7 @@ open class BaseTest {
}

@JvmStatic
@DynamicPropertySourcElo, jestem debilem i potrzebuję pomocy. Mam fedorę 38 zainstalowaną na btrfs z bootowaniem efi. Chciałem użyć timeshif do backupu systemu, ale ten wymaga żeby główny subvolume miał nazwę "@" . odpaliłem ubuntu live cd, zmieniłem nazwę subvolume na "@" i wyedytowałem pliki w grub oraz na partycji efi żeby zmienić odwołania do subcolume na nowe nazwy. Nie zadziałało. Odpaliłem grub rescue i kazałem mu naprawić gruba bez reinstalacji samego gruba - nic to nie dało. Więc zainstalowałem na drugiej partycji drugą fedorę z nadzieją że ta zainstaluje nowego gruba i wykryje starą fedorę ale tak się nie stało i do tego chyba nadpisała mi partycję efi.
e
@DynamicPropertySource
fun realDataSourceURL(registry: DynamicPropertyRegistry) {
registry.add("spring.datasource.url") { "jdbc:postgresql://localhost:${postgres.firstMappedPort}/postgres" }
}
Expand All @@ -80,12 +87,41 @@ class TestAuthenticationConfiguration() {

@Bean
@Qualifier("defaultUserId")
@Scope
fun defaultUserId() = UUID.randomUUID()

@Bean
fun restTemplateBuilder(@Qualifier("defaultUserId") defaultUserId: UUID): RestTemplateBuilder =
RestTemplateBuilder().defaultHeader("X-USER-ID", defaultUserId.toString())

@Bean
@Primary
fun webTestClient(
@Qualifier("defaultUserId") defaultUserId: UUID,
applicationContext: ApplicationContext
): WebTestClient {
return WebTestClient
.bindToServer()
.baseUrl("http://localhost:8080")
.defaultHeader("X-USER-ID", defaultUserId.toString())
.build();
}


@Bean
@Primary
fun webClient(
@Qualifier("defaultUserId") defaultUserId: UUID,
applicationContext: ApplicationContext
): WebClient {
return WebClient
.builder()
.baseUrl("http://localhost:8080")
.defaultHeader("X-USER-ID", defaultUserId.toString())
.build();
}


@Bean
@Order(value = Ordered.HIGHEST_PRECEDENCE)
fun testFilterChain(http: ServerHttpSecurity) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import org.axonframework.queryhandling.QueryGateway
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.annotation.DirtiesContext
import java.util.*

@SpringBootTest
Expand All @@ -25,6 +26,7 @@ class BookTest : BaseTest() {
lateinit var queryGateway: QueryGateway

@Test
@DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD)
fun givenReturnedBookWhenQueriedForAllBooksThenBookIsProperlyDefined() = runBlocking {
val party = Party.User(UUID.randomUUID())
val borrowingParty = Party.User(UUID.randomUUID())
Expand Down Expand Up @@ -54,6 +56,7 @@ class BookTest : BaseTest() {


@Test
@DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD)
fun givenBorrowedBookWhenDifferentPartyReturnsThenFails(): Unit = runBlocking {
val party = Party.User(UUID.randomUUID())
val borrowingParty = Party.User(UUID.randomUUID())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import com.ksidelta.libruch.BaseTest
import com.ksidelta.libruch.utils.assertBadRequest
import com.ksidelta.libruch.utils.assertBodyThat
import com.ksidelta.libruch.utils.assertOK
import com.ksidelta.libruch.utils.eventuallyConfigured
import kotlinx.coroutines.runBlocking
import org.hamcrest.CoreMatchers.equalTo
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
Expand All @@ -20,11 +22,13 @@ class BooksE2ETest : BaseTest() {
val bookIsbn = "978-0134494166"

@Test
@DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD)
fun whenBookAddedThenSucceeds() {
createBook(bookIsbn).assertOK()
}

@Test
@DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD)
fun givenBookBorrowedWhenBorrowedAgainThenErrorIs() {
val book = createBook(bookIsbn)
borrowBook(book.body!!.id).assertOK()
Expand All @@ -34,20 +38,22 @@ class BooksE2ETest : BaseTest() {

@Test
@DirtiesContext(methodMode = DirtiesContext.MethodMode.BEFORE_METHOD)
fun given2BooksWhenListedThenBothPresent() {
suspend fun given2BooksWhenListedThenBothPresent() = runBlocking {
val book1 = createBook(bookIsbn).body!!.id
val book2 = createBook(bookIsbn).body!!.id

listBooks().assertBodyThat(
equalTo(
BookAvailabilityListDTO(
listOf(
BookAvailabilityDTO(book1, bookIsbn, BookState.AVAILABLE),
BookAvailabilityDTO(book2, bookIsbn, BookState.AVAILABLE),
eventuallyConfigured {
listBooks().assertBodyThat(
equalTo(
BookAvailabilityListDTO(
listOf(
BookAvailabilityDTO(book1, bookIsbn, BookState.AVAILABLE),
BookAvailabilityDTO(book2, bookIsbn, BookState.AVAILABLE),
)
)
)
)
)
}
}

fun createBook(bookIsbn: String) =
Expand Down
Loading

0 comments on commit 8397a12

Please sign in to comment.