3 điểm bởi GN⁺ 2025-12-30 | 1 bình luận | Chia sẻ qua WhatsApp
  • Maintainer cốt lõi của Mockito cho biết sẽ kết thúc khoảng 10 năm đảm nhiệm vai trò bảo trì tính đến tháng 3/2026, và có kế hoạch chuyển giao quyền hạn dần dần trong vài tháng tới
  • Ông nhắc đến thay đổi chính sách về agent trên JVM 22 như một trong những nguyên nhân trực tiếp dẫn đến quyết định này; dù đồng tình với thay đổi vì mục đích bảo mật, nhưng yêu cầu chuyển đổi một chiều không có phương án thay thế và thiếu cân nhắc ở cấp hệ sinh thái đã trở thành gánh nặng lớn
  • Ông giải thích rằng, dù Mockito là một trong những bên sử dụng JVM agent nhiều nhất, cấu trúc mà họ phải tự gánh việc giải quyết vấn đề không có hỗ trợ từ công cụ build hay thảo luận mang tính hợp tác đã dẫn tới cạn kiệt nguồn lực và trách nhiệm quá tải
  • Một yếu tố khác được chỉ ra là độ phức tạp mang tính cấu trúc của việc hỗ trợ Kotlin; các tính năng không khớp với cách JVM hoạt động đặc thù của Kotlin đã làm tăng API trùng lặp và logic phân nhánh bên trong Mockito, khiến việc bảo trì trở nên khó khăn hơn
  • Gần đây, ông cảm thấy có nhiều niềm vui và động lực hơn khi làm việc với Servo, web engine viết bằng Rust, và khi xét đến quỹ thời gian cá nhân có hạn, ông đi đến kết luận rằng rất khó tiếp tục công việc bảo trì tình nguyện khi nó trở nên giống như một nghĩa vụ

Cột mốc 10 năm và quyết định chuyển giao vai trò

  • Tháng 3/2026 sẽ đánh dấu 10 năm ông bảo trì Mockito, và ông xem thời điểm đó là một bước ngoặt tự nhiên để chuyển giao trách nhiệm
  • Trong vài tháng tới, ông dự định tập trung vào chuyển giao tri thức và ổn định quá trình chuyển tiếp với tư cách maintainer hiện tại
  • Các thảo luận về mô hình bảo trì kế tiếp và lộ trình dài hạn sẽ được tiến hành trong một GitHub issue riêng

Sự kiệt sức do thay đổi chính sách JVM agent

  • Bối cảnh để artifact mặc định trong Mockito 5 chuyển sang JVM agent là thay đổi chính sách từ JVM 22, khi việc gắn dynamic agent bị đưa ra sau một flag
  • Ông đồng ý với chủ đích thay đổi từ góc độ bảo mật, nhưng chỉ ra vấn đề ở chỗ quyết định bị xem như chuyện đã rồi mà không có thiết kế thay thế hay hỗ trợ migration
  • Dù Mockito từ lâu thường được dùng như ví dụ đi đầu cho các tính năng của JVM, nhưng trong thay đổi lần này vòng phản hồi mang tính hợp tác đã không vận hành
  • Ông đánh giá rằng thực tế hỗ trợ ở cấp công cụ build cho agent vẫn còn thiếu cho thấy mức độ ưu tiên của tính năng này vẫn thấp
  • Ông nhấn mạnh rằng nếu maintainer là người đóng góp tự nguyện bị đặt dưới áp lực quá mức, cấu trúc cộng tác của open source có thể dễ dàng sụp đổ

Gánh nặng cấu trúc do hỗ trợ Kotlin gây ra

  • Ông không phủ nhận sự lan rộng của Kotlin, nhưng do khác biệt trong cách hoạt động nội bộ của JVM, nhiều luồng xử lý dành riêng cho Kotlin đã được thêm vào mockito-core
  • Có những trường hợp các tính năng Kotlin như hàm suspend không hoạt động nhất quán, làm tăng sự trùng lặp API và độ phức tạp
  • Kết quả là codebase ngày càng thành “spaghetti” và độ khó bảo trì tăng lên, và ông thẳng thắn nói rằng bản thân không thấy hứng thú với kiểu công việc này
  • Tương lai thiên về Kotlin cũng đã làm suy yếu động lực bảo trì Mockito trong dài hạn

Tìm lại niềm vui từ các hoạt động open source khác

  • Ông đã đóng góp cho nhiều dự án open source, và gần đây tìm lại được niềm vui phát triển phần mềm khi làm việc với Servo, web engine viết bằng Rust
  • Trong những lựa chọn giới hạn vào buổi tối, các dự án khác mang lại sự hài lòng lớn hơn so với Mockito, và tình trạng này đã kéo dài
  • Ông cho rằng việc bảo trì dựa trên tinh thần tình nguyện ở trong trạng thái bị cảm nhận như một nghĩa vụ suốt thời gian dài là điều không mong muốn

Bối cảnh tổng hợp của quyết định và thông điệp đưa ra

  • Cảm giác hoài nghi do thay đổi chính sách JVM, giới hạn trong cấu trúc hỗ trợ Kotlin, và việc lấy lại động lực từ các dự án khác là những yếu tố cốt lõi dẫn đến quyết định này
  • Ông thừa nhận các yếu tố đó không nhất thiết áp dụng giống nhau với mọi contributor, và những người khác có thể tích cực hơn trong việc hỗ trợ Kotlin
  • Ông quyết định rời vai trò với nhận định rằng việc thay maintainer sẽ có lợi hơn cho sức khỏe dài hạn của dự án
  • Ông đánh giá trải nghiệm bảo trì open source bản thân nó là một vinh dự và đặc quyền, đồng thời khuyến khích những người khác cũng tham gia đóng góp trên tinh thần tình nguyện

1 bình luận

 
GN⁺ 2025-12-30
Ý kiến trên Hacker News
  • Khi làm dự án thứ hai ở Google, tôi đã từ bỏ hoàn toàn mocking
    Khi viết lại hệ thống bằng GWT, chúng tôi ép buộc test coverage, nhưng ai cũng chỉ test service của mình và tiêm mock bằng DI
    Kết quả là hệ thống trở nên cực kỳ mong manh, và một service mới 8 tuần tuổi đã mang cảm giác như legacy code
    Chỉ cần đổi thứ tự backend hoặc số lần gọi là phải dành cả ngày để sửa mock
    Cấu trúc module Guice cũng phức tạp, nên để tiêm mock cho môi trường test thì phải tạo ra một injector hoàn toàn khác, rốt cuộc test và production lại thành hai môi trường khác nhau
    Ngoài ra, vô số nguồn lực kỹ thuật còn bị lãng phí vào các cuộc tranh cãi EasyMock vs Mockito
    Từ đó về sau tôi hầu như không dùng mock nữa. Thay vào đó, tôi nghĩ làm một service dummy đơn giản để mô phỏng hành vi thực tối thiểu sẽ tốt hơn nhiều
    Đến giờ tôi vẫn cảnh giác khi thấy ai đó quá ám ảnh với mock

    • Nếu đó là “một phiên bản dummy có hành vi đúng tối thiểu” thì chẳng phải đó chính là định nghĩa của mock sao?
    • Nếu không triển khai dummy đó bằng mock thì tức là bạn đang dùng mock sai cách
    • Tôi cũng đi đến kết luận tương tự ở Google. Trong đa số trường hợp, tôi nghĩ fake tốt hơn mock. Tuy nhiên, nếu không ở trong môi trường như Google nơi có thể truy cập mọi source, vẫn có những lúc cần đến mock
    • Tôi chỉ dùng Mockito trong những tình huống bất khả kháng như refactor legacy code hoặc test thư viện bên ngoài. Nó tuyệt đối không phải lựa chọn đầu tiên
    • Việc lạm dụng mock bắt nguồn từ sự hiểu sai về “test pyramid”. Vì chỉ nhấn mạnh unit test nên người ta tạo ra hàng loạt bài test mong manh và ít giá trị. AI đang tự động sinh ra kiểu test này khiến tình hình càng tệ hơn
  • Tôi đã dùng Mockito trong Kotlin suốt 4 năm, và trong 99% trường hợp nó hoàn toàn dùng ổn
    Những tình huống phức tạp hoặc gây rối phần lớn là do tôi chưa tách bạch mối quan tâm đủ tốt
    Nó gần như không khác MockK là mấy, chủ yếu chỉ khác cú pháp. Tuy vậy, nếu Mockito ngừng được bảo trì thì có lẽ tôi sẽ cân nhắc thay thế

    • Nhìn những cuộc tranh luận kiểu này, tôi lại thấy đó là bằng chứng dự án đã thành công. Xin nâng ly cảm ơn nhà phát triển đã cống hiến hơn 10 năm
    • Đây có vẻ không phải là sự giận dữ, mà giống một dòng chảy tự nhiên như việc chuyển dần sang Kotlin và Rust
    • Tôi nghĩ lẽ ra ngay từ đầu nên từ chối hỗ trợ Kotlin. Sẽ tốt hơn nếu có một framework riêng cho Kotlin
    • Vấn đề không nằm ở bản thân công cụ. Vì mock và spy quá tiện nên người ta không còn thiết kế cấu trúc test cho đúng cách mới là vấn đề
  • Mock hiệu quả nhất khi ứng dụng có 4~5 tầng
    Trước đây tôi cũng từng lạm dụng DI để tạo ra một mạng lưới mã nguồn phức tạp, nhưng giờ tôi giới hạn số tầng và giữ cấu trúc nhất quán
    Tôi dùng mock cho test từng class riêng lẻ, và dùng integration test để kiểm chứng yêu cầu
    Rốt cuộc điều quan trọng không phải là công cụ mà là kỷ luật của lập trình viên

  • Mockito là framework mocking phổ biến nhất trong Java

    • Nhưng sau khi trải qua địa ngục test được tạo ra bằng nó, tôi có cảm giác như tuổi thọ của mình bị bào mòn
    • Trong tiếng Tây Ban Nha, nó có nghĩa là “cục gỉ mũi nhỏ”, nên cái tên nghe khá buồn cười
  • Do thay đổi ở nền tảng, Mockito đã chuyển sang dựa trên agent, vì từ JVM 22 việc nạp agent động bị ẩn sau một cờ cấu hình
    Những thay đổi như vậy có thể làm chậm việc áp dụng trong môi trường enterprise

    • Thực ra chỉ cần thêm một cờ khi chạy test là xong
    • Dù sao thì đa số doanh nghiệp vẫn còn đang chuyển từ Java 8 sang 17, nên chuyện JVM 22 vẫn còn rất xa
  • Tôi cảm thấy thay đổi ở nền tảng đã đẩy quá nhiều trách nhiệm sang cộng đồng Mockito
    Kiểu chỉ trích rằng họ đang “chặn hệ sinh thái JVM” là không lành mạnh

    • Nhưng đội JDK đã báo trước những thay đổi này từ nhiều năm nay. Chỉ cần thêm một chút cấu hình là vẫn có thể dùng các tính năng động, và đây là lựa chọn đúng đắn vì tối ưu nền tảng và bảo mật
  • Việc bảo trì mã nguồn mở thật sự có vẻ là một công việc bào mòn con người
    Nếu là tôi thì chắc đã archive rồi rời tay từ lâu. Mong Tim giờ có thể tìm được sự bình yên

    • Dù vậy, tôi nghĩ đó vẫn là một màn rút lui đầy phẩm giá. Tôi tôn trọng những nỗ lực đã bỏ ra suốt thời gian dài, và những thành tựu Tim đạt được sẽ mãi đáng tự hào
  • Tôi muốn gửi lời cảm ơn tới TimvdLippe. Anh đã cho thấy một tầm nhìn và sự cống hiến tuyệt vời

  • Mockito vẫn ổn nếu được dùng bởi người thực sự hiểu về testing
    Trong bất kỳ ngôn ngữ hay framework nào, test tệ là lỗi của người viết

  • “Agent” là công cụ có thể gắn vào JVM để instrument và thay đổi ứng dụng đang chạy
    Profiler, debugger, công cụ monitoring... đều dùng cơ chế này
    Từ Java 21, nó bị tắt mặc định để tăng cường bảo mật, và chỉ được cho phép qua cờ -XX:+EnableDynamicAgentLoading
    Xem thêm trong tài liệu JEP 451

    • Trong cùng tài liệu JEP 451: Prepare to Disallow the Dynamic Loading of Agents có phần giải thích bối cảnh
    • Trước đây có thể kết nối debugger qua cổng trong lúc chạy, nhưng do vấn đề bảo mật nên giờ phải khai báo agent rõ ràng ngay từ lúc khởi động