【问题标题】:How to test a state stored aggregate that doesn't produce events如何测试不产生事件的状态存储聚合
【发布时间】:2021-08-16 15:38:25
【问题描述】:

我想使用 AggregateTestFixture 测试状态存储的聚合。但是我得到AggregateNotFoundException: No 'given' events were configured for this aggregate, nor have any events been stored. 错误。

我在命令处理程序中更改聚合的状态并且不应用任何事件,因为我不希望我的域条目表不必要地增长。

这是我的聚合外部命令处理程序;

open class AllocationCommandHandler constructor(
    private val repository: Repository<Allocation>,
) {
    @CommandHandler
    fun on(cmd: CreateAllocation) {
        this.repository.newInstance {
            Allocation(
                cmd.allocationId
            )
        }
    }

    @CommandHandler
    fun on(cmd: CompleteAllocation) {
        this.load(cmd.allocationId).invoke { it.complete() }
    }

    private fun load(allocationId: AllocationId): Aggregate<Allocation> =
        repository.load(allocationId)

}

这是汇总;

@Entity
@Aggregate
@Revision("1.0")
final class Allocation constructor() {

    @AggregateIdentifier
    @Id
    lateinit var allocationId: AllocationId
        private set

    var status: AllocationStatusEnum = AllocationStatusEnum.IN_PROGRESS
        private set

    constructor(
        allocationId: AllocationId,
    ) : this() {
        this.allocationId = allocationId
        this.status = AllocationStatusEnum.IN_PROGRESS
    }

    fun complete() {
        if (this.status != AllocationStatusEnum.IN_PROGRESS) {
            throw IllegalArgumentException("cannot complete if not in progress")
        }

        this.status = AllocationStatusEnum.COMPLETED

        apply(
            AllocationCompleted(
                this.allocationId
            )
        )
    }
}

此聚合中没有 AllocationCompleted 事件的事件处理程序,因为它被另一个聚合监听。

所以这里是测试代码;

class AllocationTest {
    private lateinit var fixture: AggregateTestFixture<Allocation>

    @Before
    fun setUp() {
        fixture = AggregateTestFixture(Allocation::class.java).apply {
            registerAnnotatedCommandHandler(AllocationCommandHandler(repository))
        }
    }

    @Test
    fun `create allocation`() {
        fixture.givenNoPriorActivity()
            .`when`(CreateAllocation("1")
            .expectSuccessfulHandlerExecution()
            .expectState {
                assertTrue(it.allocationId == "1")
            };
    }

    @Test
    fun `complete allocation`() {
        fixture.givenState { Allocation("1"}
            .`when`(CompleteAllocation("1"))
            .expectSuccessfulHandlerExecution()
            .expectState {
                assertTrue(it.status == AllocationStatusEnum.COMPLETED)
            };
    }
}

create allocation 测试通过,我在complete allocation 测试中得到错误。

【问题讨论】:

    标签: spring-boot hibernate kotlin jpa axon


    【解决方案1】:

    givenNoPriorActivity 实际上并不打算与 State-Stored 聚合一起使用。最近对AggregateTestFixture 进行了调整以支持此功能,但这将与 Axon 4.6.0 一起发布(当前最新版本是 4.5.1)。

    但这并没有改变我觉得奇怪的是complete allocation 测试失败的事实。使用givenStateexpectState 方法是可行的方法。也许 Kotlin/Java 组合现在正在发挥作用;你有没有试过用纯 Java 做同样的事情,只是为了确定?

    无论如何,您分享的异常来自AggregateTestFixture 中的RecordingEventStore。仅当在后台(由夹具)使用事件源存储库时才会发生这种情况,因为它将读取事件。 可能是罪魁祸首,是givenNoPriorActivity 的使用。请尝试将其替换为 givenState() 提供一个空的 Aggregate 实例。

    【讨论】:

    • 在将命令处理程序注册到聚合夹具时,我使用了 AggregateFixture 的 getRepository() 方法。因此,在调用 givenState 方法之前,它将存储库初始化为事件存储。我相信这是我的问题,在注册命令处理程序之前,我需要一种方法来选择 InMemoryRepository 而不是事件源。我也试过用givenState而不是givenNoPriorActivity,结果是一样的。
    • 啊好吧,这听起来像是罪魁祸首。为什么在实际开始测试之前需要检索 repo?测试夹具通常只是为您执行此操作。仅供参考,将在 4.6.0 中引入的上述解决方案应该也可以解决您描述的这种情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多