SpectoLabs / hoverfly-java

Java binding for Hoverfly
Apache License 2.0
168 stars 58 forks source link

Allow static method or class or none as HoverflySimulate.Source #306

Closed silk-bahamut closed 3 weeks ago

silk-bahamut commented 3 weeks ago

I really like the SimulationSource.dsl declaration type and since the begin I have a global method to init Hoverfly with this (it started before you could inject Hoverfly in a test).

I tried to switch to 0.18 but all my tests fail because I didn't set any configuration for source, so the framework switch to default mode that looks up for a json with the class name.

I have a LOT of test and would like to configure Hoverfly only once even if some inherited test classes do not need it.

The different alternative that could be useful would be :

Otherwise, I will export all my current configuration to a json file but the completion in java is quite useful to write the dsl

tommysitu commented 3 weeks ago

Hi @silk-bahamut I've just checked the commits in v0.18.0, it only adds support to response body file and post serve action API, all backward compatible, there hasn't been any update for SimulationSource for a while. Could you elaborate what is breaking your test after the update, and what errors do you see please?

silk-bahamut commented 3 weeks ago

Hi, sure

I have an abstract class with these headers :

@ExtendWith({HoverflyExtension.class})
@HoverflySimulate(config = @HoverflyConfig(webServer = true, disableTlsVerification = true))
public abstract class TestBase {

In my beforeEach of that abtract class I do the init

@BeforeEach
public final void setupWebApp(Hoverfly hoverfly) throws Exception {
    if (defaultSimulationSources == null) {
      defaultSimulationSources = dsl(
          initSimulations1(),
          initSimulations2(),
          ...
      );
  }
  hoverfly.reset();
  hoverfly.simulate(defaultSimulationSources);
}

Not the most beautiful use case but we start with an old version of hoverfly some years ago. Each methods load json response file and build the requirements to match the calls.

After that I have all the real tests that extends the TestBase class

class SomeSubTest extends TestBase {
  @Test
  void shouldWork() {
    Assertions.assertThat(true).isTrue();
  }
}

But when I try to start this test, I go the following error :

java.lang.IllegalArgumentException: Cannot load default path resource: 'package_SomeSubTest.json'

    at io.specto.hoverfly.junit.core.SimulationSource.lambda$defaultPath$3(SimulationSource.java:86)
    at io.specto.hoverfly.junit.core.Hoverfly.simulate(Hoverfly.java:304)
    at io.specto.hoverfly.junit5.HoverflyExtension.beforeAll(HoverflyExtension.java:124)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
Caused by: java.lang.IllegalArgumentException: Resource not found with name: hoverfly/com_wedoogift_gateway_admin_shop_ConditionServiceUnitTest.json
    at io.specto.hoverfly.junit.core.HoverflyUtils.lambda$getClasspathResourceAsStream$1(HoverflyUtils.java:58)
    at java.base/java.util.Optional.orElseThrow(Optional.java:403)
    at io.specto.hoverfly.junit.core.HoverflyUtils.getClasspathResourceAsStream(HoverflyUtils.java:58)
    at io.specto.hoverfly.junit.core.SimulationSource.lambda$defaultPath$3(SimulationSource.java:83)
    ... 3 more

I'm currently using these versions :

silk-bahamut commented 3 weeks ago

From what I found while debugging : before, I was not entering the block if isAnnotated(annotatedElement, HoverflySimulate.class) in HoverflyExtension Now, it seems to be detected and it enters, so it switch from SimulationSource.empty() to SimulationSource.defaultPath()

When I remove the @HoverflySimulate, I'm back with how it worked before and everything great for me. But still, allowing to keep the empty source would be great

tommysitu commented 3 weeks ago

ah, i think it's because of this change: https://github.com/SpectoLabs/hoverfly-java/pull/296, the annotation is now inherited, so your subclass test would have inherited the superclass's annotations too: @HoverflySimulate(config = @HoverflyConfig(webServer = true, disableTlsVerification = true))

tommysitu commented 3 weeks ago

Since your subclass has inherited the @HoverflySimulate annotation, and you haven't specified a source, it will just try to read a file with the same name as the test class from the test resources folder, when the file is not found, it just blows up. That's the current behaviour of the annotation if no source is provided. We can't change this as it will introduce breaking changes for other users.

What we can do to fix it is adding a meta annotation for source @EmptySource, and you can add it to your base class like @HoverflySimulate(source = @EmptySource, config = @HoverflyConfig(webServer = true, disableTlsVerification = true)) so that any subclass won't try to read simulations from the default path. What do you think?

silk-bahamut commented 3 weeks ago

That would be awesome

I was more thinking of add an EMPTY value to SourceType but that's great

If later a SimulationSource could be provided from a static java method, that would be also a great addition to avoid all my custom tweaks 😄

Thank you for your quick answer.

tommysitu commented 3 weeks ago

this is the best I can do, because java annotation doesn't support inheritance: https://github.com/SpectoLabs/hoverfly-java/pull/307/files#diff-997320e2555b00b04f9f43ca5ff2a8ab40bf632fcdb8b686e16b5229c2a62b75R12

silk-bahamut commented 3 weeks ago

It's perfect

tommysitu commented 3 weeks ago

resolved in this release: https://github.com/SpectoLabs/hoverfly-java/releases/tag/0.19.1