简体   繁体   中英

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?

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.

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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM