DEV Community

mhossen
mhossen

Posted on

Java Clean Code Tip for Testers: Use try-with-resources Like a Pro

When writing Java tests—be it for automation, backend validation, or reading test data—you'll often deal with resources like files, streams, or database connections. Managing these resources properly is crucial to prevent issues like memory leaks or file locks.

Let's explore how try-with-resources, introduced in Java 7, can help you write cleaner and safer code.


😬 The Traditional Way (Before Java 7)

BufferedReader reader = null;
try {
    reader = new BufferedReader(new FileReader("data.csv"));
    String line;
    while ((line = reader.readLine()) != null) {
        // process line
    }
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (reader != null) {
        try {
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

This approach is verbose and error-prone. Forgetting to close resources can lead to resource leaks.


✅ The Modern Way: try-with-resources

try (BufferedReader reader = new BufferedReader(new FileReader("data.csv"))) {
    reader.lines().forEach(System.out::println);
} catch (IOException e) {
    System.err.println("Error reading file: " + e.getMessage());
}
Enter fullscreen mode Exit fullscreen mode

With try-with-resources, Java automatically closes the resource at the end of the statement, even if exceptions occur. This leads to cleaner and more reliable code.


👩‍💻 Why Testers Should Care

As a tester, you might:

  • Read test data from files
  • Write logs during test execution
  • Interact with databases
  • Handle input/output streams

Using try-with-resources ensures that these resources are properly closed, reducing the risk of resource leaks and making your tests more robust.


🧪 Real-World Example: Logging in Tests

Here's a utility class to write logs:

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class TestLogger {

    public static void writeLog(String message, String path) {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(path, true))) {
            writer.write(message);
            writer.newLine();
        } catch (IOException e) {
            System.err.println("Could not write log: " + e.getMessage());
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Usage in a test:

@Test
public void testUserLogin() {
    TestLogger.writeLog("Login test started", "logs/test-log.txt");
    // perform test steps
    TestLogger.writeLog("Login test passed", "logs/test-log.txt");
}
Enter fullscreen mode Exit fullscreen mode

This approach ensures that the BufferedWriter is closed properly after writing, even if an exception occurs.


🔄 Handling Multiple Resources

You can manage multiple resources in a single try-with-resources statement:


try (
    InputStream inStream = new FileInputStream("input.txt");
    OutputStream outStream = new FileOutputStream("output.txt")
) {
    byte[] buffer = new byte[1024];
    int length;
    while ((length = inStream.read(buffer)) > 0) {
        outStream.write(buffer, 0, length);
    }
} catch (IOException e) {
    e.printStackTrace();
}
Enter fullscreen mode Exit fullscreen mode

Resources are closed in the reverse order of their declaration.


🧠 TL;DR

  • Use try-with-resources for any resource that implements AutoCloseable (e.g., files, streams, database connections).
  • It simplifies your code and improves test reliability.
  • Cleaner code leads to fewer bugs and better maintenance. 🧼

AWS GenAI LIVE image

Real challenges. Real solutions. Real talk.

From technical discussions to philosophical debates, AWS and AWS Partners examine the impact and evolution of gen AI.

Learn more

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.

Tiger Data image

🐯 🚀 Timescale is now TigerData: Building the Modern PostgreSQL for the Analytical and Agentic Era

We’ve quietly evolved from a time-series database into the modern PostgreSQL for today’s and tomorrow’s computing, built for performance, scale, and the agentic future.

So we’re changing our name: from Timescale to TigerData. Not to change who we are, but to reflect who we’ve become. TigerData is bold, fast, and built to power the next era of software.

Read more

👋 Kindness is contagious

Explore this compelling article, highly praised by the collaborative DEV Community. All developers, whether just starting out or already experienced, are invited to share insights and grow our collective expertise.

A quick “thank you” can lift someone’s spirits—drop your kudos in the comments!

On DEV, sharing experiences sparks innovation and strengthens our connections. If this post resonated with you, a brief note of appreciation goes a long way.

Get Started