SpectoLabs / hoverfly-java

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

[0.14.0] Working directory doesn't seem to be relative to workspace directory #247

Closed BrainStone closed 6 months ago

BrainStone commented 3 years ago

Description of the bug

The working directory of the hoverfly instance seems to be located in the temproary folder instead of the workspace/project directory. And since hoverfly requires relative paths this makes it almost impossible to reliably specify your response files let alone specify them in a way that is not machine dependent.

Instead the working directory should in the default path (src/test/resources/hoverfly) or where the simulation file is so relative paths can be used easily

Steps to reproduce the issue

Start a simulation from a simulation file. Specify a path relative to the default path or the simulation JSON.

Example gist: https://gist.github.com/BrainStone/14b5facb30a17e3d0c658d12ba49796d

Observed result

Hoverfly errors out:

[02:05:12.589][Test worker][WARN ][i.s.h.junit.api.HoverflyClient]: Failed to set simulation: Unexpected response (code=500, message={"error":"An error occurred: open test.json: The system cannot find the path specified."}{"data":{"pairs":[],"globalActions":{"delays":[],"delaysLogNormal":[]}},"meta":{"schemaVersion":"v5.1","hoverflyVersion":"v1.3.1","timeExported":"2020-11-29T02:05:12+01:00"}}
)

Expected result

The simulation just working fine and being able to find the files.

Additional relevant information

Only way I was able to get it working was using a pseudo absolut path. So just a bunch of ../../../.. until you eventually reach the root dir, then specify the path like you would with an absolute path, excluding the drive specification on Windows (needs to be on the same drive)

BrainStone commented 3 years ago

Issue still present on 0.14.0

tommysitu commented 3 years ago

👀

tommysitu commented 3 years ago

@BrainStone we haven't supported the bodyFile feature in hoverfly-java properly yet. In hoverfly, there is a flag you can set the relative file path of a body file:

  -response-body-files-path string
        When a response contains a relative bodyFile, it will be resolved against this path (default is CWD)

will try to add the support to this in the next release

BrainStone commented 3 years ago

Awesome. When could I expect that to be done?

And excuse the question but is there a way to specify the flag when doing unit tests?

tommysitu commented 3 years ago

There are two workarounds actually:

  1. you can copy hoverfly binary to your test resource folder, and set its location with this config:

    localConfigs().binaryLocation("/absolute/path/to/hoverfly/directory")
  2. or you can pass hoverfly flag using this config

    localConfigs().addCommands("-response-body-files-path", "/absolute/path/to/your/test/resource/folder")
BrainStone commented 3 years ago

Ok. Will give that a shot. Thanks very much!

BrainStone commented 3 years ago

That worked great!

Looking forward to having that being done automatically.

For people that might stumble across this in the future, here is my code:

public class TestApi {
  private static final String simulationFile = "simulation.json";

  @ClassRule
  public static final HoverflyRule hoverflyRule =
      HoverflyRule.inSimulationMode(
          SimulationSource.defaultPath(simulationFile),
          HoverflyConfig.localConfigs()
              .addCommands(
                  "-response-body-files-path",
                  getPathOfResource(simulationFile).getParent().toAbsolutePath().toString()));

  private static URL findResourceOnClasspath(String resourceName) {
    final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    return Optional.ofNullable(classLoader.getResource(resourceName))
        .orElseThrow(
            () -> new IllegalArgumentException("Resource not found with name: " + resourceName));
  }

  @SneakyThrows(URISyntaxException.class)
  private static Path getPathOfResource(String resource) {
    return Paths.get(
        findResourceOnClasspath(HoverflyConstants.DEFAULT_HOVERFLY_RESOURCE_DIR + '/' + resource)
            .toURI());
  }
}

(@SneakyThrows is from lombok. If you don't have that, just catch the exception and rethrow it wrapped in a RuntimeException)

malika15 commented 6 months ago

Hi @tommysitu , Is bodyFile now added to hoverfly-junit5 0.17.1?

I am using HoverflySimulate annotation and could not get the relative path working and hence used absolute path as shown below which I cannot use since it varies from machine to machine

@HoverflySimulate( config = @HoverflyConfig( proxyPort = 8501, // Proxy port for hoverfly adminPort = 8889, // Admin port for accessing hoverfly dashboard webServer = true, // Configures hoverfly as web server logLevel = LogLevel.INFO, commands = {"-response-body-files-path", "C:/MyApi/src/componentTest/resources/hoverfly/provider-responses"}), source = @HoverflySimulate.Source(value = "hoverfly/simulation.json", type = HoverflySimulate.SourceType.CLASSPATH)) @ExtendWith(HoverflyExtension.class)

tommysitu commented 6 months ago

bodyFile is not properly supported in hoverfly-java yet, I can take a look

malika15 commented 6 months ago

Thanks much @tommysitu

tommysitu commented 6 months ago

Just raised a PR that fixes this issue: https://docs.hoverfly.io/projects/hoverfly-java/en/latest/pages/corefunctionality/configuration.html#response-body-files

malika15 commented 6 months ago

Thanks a lot @tommysitu . Is this released in version 0.18.0 ?

malika15 commented 6 months ago

Hi @tommysitu , I tried using version 0.18.0 with one of the below HoverflyConfig. Both kinds of config are failing with Exception shown below. (But 0.17.1 version worked with commands and absolute path)

relativeResponseBodyFilesPath = "hoverfly/provider-responses"

or

commands = {"-response-body-files-path", "C:/MyApi/src/componentTest/resources/hoverfly/provider-responses"})

I can see in the logs relativePath is getting resolved to absolute path . But Hoverfly is failing with the below error :

Failed to set simulation: Unexpected response (code=500, message={"error":"An error occurred: data.pairs[0].response open \C:\Projects\MyApi\build\resources\componentTest\hoverfly\security-api\validateSystemTokenWithSecurityExemptionsResponse.json: The filename, directory name, or volume label syntax is incorrect."}) io.specto.hoverfly.junit.api.HoverflyClientException: Failed to set simulation: Unexpected response (code=500, message={"error":"An error occurred: data.pairs[0].response open \C:\Projects\MyApi\build\resources\componentTest\hoverfly\security-api\validateSystemTokenWithSecurityExemptionsResponse.json: The filename, directory name, or volume label syntax is incorrect."}) at app//io.specto.hoverfly.junit.api.OkHttpHoverflyClient.setSimulation(OkHttpHoverflyClient.java:103)

tommysitu commented 6 months ago

@malika15 your files should be in the java src/test/resources folder so that when your project is built, the response body files can be found in the classpath. This is based on the assumption of standard Maven project structure: https://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html Also please check out the hoverfly-java doc: https://docs.hoverfly.io/projects/hoverfly-java/en/latest/pages/corefunctionality/configuration.html#response-body-files

If you have different project structure and you require an absolute path, use the absoluteResponseBodyFilesPath config option instead.

malika15 commented 6 months ago

Thank you @tommysitu .

I moved the files to src/test/resources but it still failed with the same reason

On further investigation , I found it's because getTestResourcesFolderPath method in HoverflyConfigValidator.java is using URL.getPath() which returns absolute path with a starting slash as shown below.

\C:\Projects\MyApi\build\resources\test\hoverfly\security-api\myresponse.json

Probably the above path works on UNIX but is failing to resolve on windows.

We may need to convert URL to a URI (For ex: Paths.get(url.toURI()).toString()) to not have the starting slash in the path as shown below:

C:\Projects\MyApi\build\resources\test\hoverfly\security-api\myresponse.json

When I manually put a breakpoint here and removed the starting slash , it worked

tommysitu commented 6 months ago

@malika15 oh I didn't test it with windows. It works on mac though. Are you able to raise a PR with the fix? Then I can test your fix on mac as well, making sure it works on yours and my machine.