Recent Posts
Archives

Posts Tagged ‘Testcontainers’

PostHeaderIcon [NDCOslo2024] No More SQLite: How to Write Tests With EF Core Using TestContainers – Daniel Ward

Amid the arduous arena of application assurance, where integration inspections intersect infrastructure intricacies, Daniel Ward, a .NET navigator and testing tactician, torpedoes the tired trope of SQLite as EF Core’s ersatz examiner. With a penchant for precision and a portfolio of pragmatic patterns, Daniel decries the discrepancies—dialect drifts, devious defaults—that delude developers into dubious dependability. His herald: TestContainers, a titan of transient testing, tethering true-to-type databases to dotnet diagnostics, ensuring examinations echo environments exactly.

Daniel dives direct: SQLite’s siren song—simplicity’s shadow—seduces with speed yet sabotages similitude, spawning spurious successes in schema shadows. Real realms revel in PostgreSQL or SQL Server; sans such sentinels, tests tantalize with triumphs that tumble in truth. His thesis: TestContainers triumphs, turbocharging temporaries—containers conjured cleanly, configured crisply—for credible, containerized corroboration.

Ditching the Decoy: Drawbacks of Database Doppelgangers

SQLite’s shortcomings spotlight starkly: syntax schisms—TOP versus LIMIT—thwart translations; transaction treatments transmute, transactions toggling differently. Daniel details dev database dilemmas: devious dependencies, drift-prone data, deployment drudgery. False flags flourish: tests triumph trivially, only to falter in flight, fostering fragile faith.

His horror stories: SQLite’s solitary schema swallows specifics, sans stored procedures or sequences; in-memory imposters ignore indexes, inflating illusions. Daniel’s decree: discard decoys for doppelgangers divine—TestContainers delivers, Docker-driven duplicates that duplicate dynamics deftly.

Containers as Champions: TestContainers’ Triumphs

TestContainers, Daniel declaims, democratizes diligence: NuGet-nimble, it nurtures nodes—Postgres pods, SQL Server ships—spinning sans setup strife. Benefits burgeon: bit-for-bit fidelity, flakeless flurries, fleet-footed forays. Reusability reigns: withReuse() recycles realms, reining runtime rigorously.

Daniel demos deftly: dotnet add package Testcontainers.PostgreSql; a builder begets a beast, beckoning a bespoke bastion. Connection strings cascade, EF contexts calibrate, tests transact transparently—Respawn resets, restoring rectitude routinely.

Precision in Practice: Pitfalls and Panaceas

Pitfalls persist: parallelism’s pandemonium, port pandemonium—Daniel dispels with Docker Desktop’s discipline, orchestration’s oversight. His heuristic: harness health checks, heed horizons—hundreds hum harmoniously, hovering at half-minutes for hordes.

Respawn’s renaissance: rollback routines, resetting relations rigorously, rectifying residue. Daniel’s distillation: TestContainers transmutes testing from torment to triumph, true tests tempering temper tantrums.

Links:

PostHeaderIcon [DevoxxGR2024] Butcher Virtual Threads Like a Pro at Devoxx Greece 2024 by Piotr Przybyl

Piotr Przybyl, a Java Champion and developer advocate at Elastic, captivated audiences at Devoxx Greece 2024 with a dynamic exploration of Java 21’s virtual threads. Through vivid analogies, practical demos, and a touch of humor, Piotr demystified virtual threads, highlighting their potential and pitfalls. His talk, rich with real-world insights, offered developers a guide to leveraging this transformative feature while avoiding common missteps. As a seasoned advocate for technologies like Elasticsearch and Testcontainers, Piotr’s presentation was a masterclass in navigating modern Java concurrency.

Understanding Virtual Threads

Piotr began by contextualizing virtual threads within Java’s concurrency evolution. Introduced in Java 21 under Project Loom, virtual threads address the limitations of traditional platform threads, which are costly to create and limited in number. Unlike platform threads, virtual threads are lightweight, managed by a scheduler that mounts and unmounts them from carrier threads during I/O operations. This enables a thread-per-request model, scaling applications to handle millions of concurrent tasks. Piotr likened virtual threads to taxis in a busy city like Athens, efficiently transporting passengers (tasks) without occupying resources during idle periods.

However, virtual threads are not a universal solution. Piotr emphasized that they do not inherently speed up individual requests but improve scalability by handling more concurrent tasks. Their API remains familiar, aligning with existing thread practices, making adoption seamless for developers accustomed to Java’s threading model.

Common Pitfalls and Pinning

A central theme of Piotr’s talk was “pinning,” a performance issue where virtual threads remain tied to carrier threads, negating benefits. Pinning occurs during I/O or native calls within synchronized blocks, akin to keeping a taxi running during a lunch break. Piotr demonstrated this with a legacy Elasticsearch client, using Testcontainers and Toxiproxy to simulate slow network calls. By enabling tracing with flags like -J-DTracePinnThreads, He identified and resolved pinning issues, replacing synchronized methods with modern, non-blocking clients.

Piotr cautioned against misuses like thread pooling or reusing virtual threads, which disrupt their lightweight design. He advocated for careful monitoring using JFR events to ensure threads remain unpinned, ensuring optimal performance in production environments.

Structured Concurrency and Scope Values

Piotr explored structured concurrency, a preview feature in Java 21, designed to eliminate thread leaks and cancellation delays. By creating scopes that manage forks, developers can ensure tasks complete or fail together, simplifying error handling. He demonstrated a shutdown-on-failure scope, where a single task failure cancels all others, contrasting this with the complexity of managing interdependent futures.

Scope Values, another preview feature, offer immutable, one-way thread locals to prevent bugs like data leakage in thread pools. Piotr illustrated their use in maintaining request context, warning against mutability to preserve reliability. These features, he argued, complement virtual threads, fostering robust, maintainable concurrent applications.

Practical Debugging and Best Practices

Through live coding, Piotr showcased how debugging with logging can inadvertently introduce I/O, unmounting virtual threads and degrading performance. He compared this to a concert where logging scatters tasks, reducing completion rates. To mitigate this, he recommended avoiding I/O in critical paths and using structured concurrency for monitoring.

Piotr’s best practices included using framework-specific annotations (e.g., Quarkus, Spring) to enable virtual threads and ensuring tasks are interruptible. He urged developers to test thoroughly, leveraging tools like Testcontainers to simulate real-world conditions. His blog post on testing unpinned threads provides further guidance for practitioners.

Conclusion

Piotr’s presentation was a clarion call to embrace virtual threads with enthusiasm and caution. By understanding their mechanics, avoiding pitfalls like pinning, and leveraging structured concurrency, developers can unlock unprecedented scalability. His engaging analogies and practical demos made complex concepts accessible, empowering attendees to modernize Java applications responsibly. As Java evolves, Piotr’s insights ensure developers remain equipped to navigate its concurrency landscape.

Links: