Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UncheckedIOException is thrown instead of a different expected exception

While refactoring Rultor to use Cactoos instead of Guava, I’m having an issue with negative tests of GithubProfileTest and GithubProfileValidationTest.

After the refactor, the positive test cases pass for both mentioned test classes, but the negative test cases that expect a particular exception fail. The affected refactored code under test is GithubProfile.assets method and GithubProfile.asset method.

I refactored assets method to look like this:

 public Map<String, InputStream> assets() throws IOException {
    final XML xml = this.read();
    final List<XML> nodes = xml.nodes("/p/entry[@key='assets']/entry");
    return new MapOf<>(
        new Mapped<>(
            nodes,
            input ->
                new MapEntry<>(
                    input.xpath("@key").get(0),
                    this.asset(input.xpath("text()").get(0))
                )
        )
    );
}

On different test cases the this.asset call is expected to throw Profile.ConfigException. Instead, upon calling the assets method, the test fails with a Unable to evaluate the expression Method threw 'java.io.UncheckedIOException' exception, and the Profile.ConfigException is simply ignored/hidden.

It seems that MapOf somehow fails to evaluate, or "hides", the exception that the call to this.asset method raised, raising itself an UncheckedIOException, so I'm unable to fix this and have the Profile.ConfigException raised.

When debugging, the UncheckedIOException doesn't contain any info whatsoever of a Profile.ConfigException being raised.

Any hints on why I might be getting this behaviour or possible solutions?

like image 778
Filipe Freire Avatar asked Oct 22 '25 15:10

Filipe Freire


2 Answers

The problem is that Iterable#next() (in JDK) doesn't allow to throw checked exceptions (like Profile.ConfigException). That's why org.cactoos.iterator.Mapped catches them all and throws UncheckedIOException instead. It's unfixable, thanks to JDK design. The best you can do is good old for loop:

public Map<String, InputStream> assets() throws IOException {
  final XML xml = this.read();
  final List<XML> nodes = xml.nodes("/p/entry[@key='assets']/entry");
  final List<MapEntry> entries = new LinkedList<>();
  for (final XML node : nodes) {
    entries.add(
      new MapEntry<>(
        input.xpath("@key").get(0),
        this.asset(input.xpath("text()").get(0)) // checked exeption here
      )
    );
  }
  return new MapOf<>(entries);
}
like image 139
yegor256 Avatar answered Oct 25 '25 06:10

yegor256


The reason is probably the conversion done in org.cactoos.func.UncheckedFunc while iterating to populate the map.

Since functional style programming usually does not play very well with exceptions, the API tries to avoid declaring checked exceptions. So you probably have to live with that.

like image 28
aventurin Avatar answered Oct 25 '25 04:10

aventurin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!