# Best practices for testing private methods

It is good practice to break down the logic of complex public methods into private methods. For instance:

<pre class="language-java"><code class="lang-java"><strong>public class Palindrome {
</strong>  private final Path inputFile;

  public Palindrome(Path inputFile) {
    this.inputFile = inputFile;
  }
  
  public boolean check() {
    return Files.lines(inputFile)
      .stream()
      .allMatch(s -> new StringBuilder(s).reverse().toString().equals(s));
  }
}
</code></pre>

After splitting out the palindrome check for a single line, we have:

```java
public class Palindrome {
  private final Path inputFile;

  public Palindrome(Path inputFile) {
    this.inputFile = inputFile;
  }
  
  public boolean check() {
    return Files.lines(inputFile).stream().allMatch(this::isPalindrome);
  }
  
  private boolean isPalindrome(String s) {
    return new StringBuilder(s).reverse().toString().equals(s);
  }
}
```

This looks much more approachable now. The private method could even be made static in this case. However, for testing the logic in this private method we have introduced another obstacle because they cannot be directly called from test cases anymore. Using reflection to call private methods would result in brittle test code that is hard to automatically refactor and is thus not recommended.

The recommended approach is to

* make the methods package-private and
* annotate them with `@VisibleForTesting` .

This annotation is available from several libraries such as Guava, Jetbrains Annotations and Assert4J.

It doesn't matter which of these libraries we choose; so, let's add the following to our build configuration, for instance:

```xml
      <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>33.4.8-jre</version>
      </dependency>
```

And then apply our recommendation:

```java
public class Palindrome {
  private final Path inputFile;

  public Palindrome(Path inputFile) {
    this.inputFile = inputFile;
  }
  
  public boolean check() {
    return Files.lines(inputFile).stream().allMatch(this::isPalindrome);
  }
  
  @VisibleForTesting
  boolean isPalindrome(String s) {
    return new StringBuilder(s).reverse().toString().equals(s);
  }
}
```

Now we can easily test the single-line palindrome check without requiring reflection or setting up a test scenario with actual input files.

{% hint style="info" %}
If you are worried about having loosened encapsulation, note that, additionally, an `arch-unit` test could be configured to ensure that these now package-private methods are only called from the scope of the class or the tests, but this is out of scope of this tutorial.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://cover-docs-preview.diffblue.com/features/tutorials/best-practices-for-testing-private-methods.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
