You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用@WebFluxTest测试Post子资源/posts/1/comments失败问题排查

问题分析与解决方案

我一眼就看出问题出在你的PostId值对象上——它没有正确实现equals()和hashCode()方法,导致Mockito的参数匹配失效了,最终测试返回空数组才触发了断言错误。

为什么会出现这个问题?

在你的getCommentsByPostId_shouldBeOk测试里,你预设了:

given(comments.findByPost(new PostId("1")))
        .willReturn(Flux.just(...));

但实际运行时,PostController的代码会创建一个全新的PostId实例:

return this.comments.findByPost(new PostId(id)); // 这里的id是"1",但这是另一个对象实例

如果PostId没有重写equals()和hashCode(),Java会用默认的对象引用比较逻辑——哪怕两个PostId("1")的内容完全一致,只要是不同的实例,Mockito就会认为这是两个不匹配的参数,不会触发你预设的返回值,而是返回默认的Flux.empty(),接口自然就返回空数组了,断言$[0].id当然找不到值。

快速验证问题的方法

你可以临时修改测试里的given语句,用参数匹配器any(PostId.class)代替具体的实例:

given(comments.findByPost(any(PostId.class)))
        .willReturn(Flux.just(Comment.builder().id("comment-id-1").content("comment of my first post").build()));

如果修改后测试通过,就坐实了是PostId的equals/hashCode问题。

最终解决方案:给PostId实现正确的equals()和hashCode()

值对象的核心特性是内容相等即对象相等,所以你需要基于id字段来实现这两个方法:

import java.util.Objects;

public class PostId {
    private final String id;

    public PostId(String id) {
        this.id = id;
        // 可选:添加非空校验,避免null值引发后续问题
        Objects.requireNonNull(id, "Post id must not be null");
    }

    public String getId() {
        return id;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        PostId postId = (PostId) o;
        return Objects.equals(id, postId.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}

实现后,Mockito就能正确识别内容相同的PostId实例是相等的,你的预设返回值会正常生效,测试就能通过了。

额外的小建议

在createCommentOfPost_shouldBeOk测试里,你预设的是comments.save(comment),但实际代码里保存的是一个全新创建的Comment实例(和测试里的comment不是同一个对象),这里也建议改用参数匹配器:

given(comments.save(any(Comment.class)))
        .willReturn(Mono.just(comment));

这样可以避免因为Comment的equals/hashCode问题导致的测试失败,让测试逻辑更健壮。

内容的提问来源于stack exchange,提问作者Hantsy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:27:20