ePages-de / restdocs-wiremock

Spring REST Docs WireMock Integration
Apache License 2.0
75 stars 27 forks source link

Stubs loaded from absolute path #60

Open raulavila opened 6 years ago

raulavila commented 6 years ago

We're trying to integrate wiremock-spring-boot-starter in our project using the default configuration (adding dependency + @WireMockTest). We have our response body files under src/test/resources/__files, which is the default location for Wiremock. When we run our tests we get this exception:

java.lang.RuntimeException: java.io.FileNotFoundException: /__files/product-catalog-response.json (No such file or directory)
    at com.github.tomakehurst.wiremock.common.BinaryFile.readContents(BinaryFile.java:38) ~[wiremock-standalone-2.10.1.jar:na]
    at com.github.tomakehurst.wiremock.http.StubResponseRenderer.renderDirectly(StubResponseRenderer.java:95) ~[wiremock-standalone-2.10.1.jar:na]
    at com.github.tomakehurst.wiremock.http.StubResponseRenderer.buildResponse(StubResponseRenderer.java:65) ~[wiremock-standalone-2.10.1.jar:na]
    at com.github.tomakehurst.wiremock.http.StubResponseRenderer.render(StubResponseRenderer.java:54) ~[wiremock-standalone-2.10.1.jar:na]
    at com.github.tomakehurst.wiremock.http.AbstractRequestHandler.handle(AbstractRequestHandler.java:47) ~[wiremock-standalone-2.10.1.jar:na]
    at com.github.tomakehurst.wiremock.servlet.WireMockHandlerDispatchingServlet.service(WireMockHandlerDispatchingServlet.java:102) ~[wiremock-standalone-2.10.1.jar:na]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
    at wiremock.org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:812) ~[wiremock-standalone-2.10.1.jar:na]
    at wiremock.org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1669) ~[wiremock-standalone-2.10.1.jar:na]
    at wiremock.org.eclipse.jetty.servlets.UserAgentFilter.doFilter(UserAgentFilter.java:83) ~[wiremock-standalone-2.10.1.jar:na]
    at wiremock.org.eclipse.jetty.servlets.GzipFilter.doFilter(GzipFilter.java:301) ~[wiremock-standalone-2.10.1.jar:na]
    at wiremock.org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652) ~[wiremock-standalone-2.10.1.jar:na]
    at wiremock.org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585) [wiremock-standalone-2.10.1.jar:na]
    at wiremock.org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127) [wiremock-standalone-2.10.1.jar:na]
    at wiremock.org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515) [wiremock-standalone-2.10.1.jar:na]
    at wiremock.org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061) [wiremock-standalone-2.10.1.jar:na]
    at wiremock.org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) [wiremock-standalone-2.10.1.jar:na]
    at wiremock.org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:110) [wiremock-standalone-2.10.1.jar:na]
    at wiremock.org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) [wiremock-standalone-2.10.1.jar:na]
    at wiremock.org.eclipse.jetty.server.Server.handle(Server.java:499) [wiremock-standalone-2.10.1.jar:na]
    at wiremock.org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:311) [wiremock-standalone-2.10.1.jar:na]
    at wiremock.org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:258) [wiremock-standalone-2.10.1.jar:na]
    at wiremock.org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:544) [wiremock-standalone-2.10.1.jar:na]
    at wiremock.org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635) [wiremock-standalone-2.10.1.jar:na]
    at wiremock.org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555) [wiremock-standalone-2.10.1.jar:na]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_144]

It looks like Wiremock is trying to find the files using an absolute path, instead of going to the classpath. In fact, if we create a __files in the root directory of our computer with the same contents the tests work fine.

We haven't been able to figure out how to configure this properly to load the contents from the classpath, is there any way to do it?

mduesterhoeft commented 6 years ago

You can use the stubPath attribute of WireMockTest to tell it where to look for the wiremock stubs. This folder is resolved as a classpath resource.

So in your case you could use.

@WireMockTest(stubPath = "__files") 
raulavila commented 6 years ago

Thanks for your response. We actually tried using what you propose, and it doesn't seem to work. We're getting this error:

wiremock.com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "productBandOutput" (class com.github.tomakehurst.wiremock.stubbing.StubMapping), not marked as ignorable (11 known properties: "response", "requiredScenarioState", "priority", "persistent", "id", "postServeActions", "request", "newScenarioState", "name", "uuid", "scenarioName"])
 at [Source: {
  "productBandOutput": [
    {
      //...
      ]
    }
  ]
}; line: 2, column: 25] (through reference chain: com.github.tomakehurst.wiremock.stubbing.StubMapping["productBandOutput"])

    at wiremock.com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:62)
    at wiremock.com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:834)
    at wiremock.com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1093)
    at wiremock.com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1478)
    at wiremock.com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1456)
    at wiremock.com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:282)
    at wiremock.com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:140)
    at wiremock.com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3814)
    at wiremock.com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2858)
    at com.github.tomakehurst.wiremock.common.Json.read(Json.java:48)
    at com.github.tomakehurst.wiremock.stubbing.StubMapping.buildFrom(StubMapping.java:66)
    at com.github.tomakehurst.wiremock.standalone.JsonFileMappingsSource.loadMappingsInto(JsonFileMappingsSource.java:82)
    at com.github.tomakehurst.wiremock.core.WireMockApp.loadMappingsUsing(WireMockApp.java:154)
    at com.github.tomakehurst.wiremock.WireMockServer.loadMappingsUsing(WireMockServer.java:121)
    at com.epages.wiremock.starter.WireMockListener.beforeTestMethod(WireMockListener.java:76)
    at org.springframework.test.context.TestContextManager.beforeTestMethod(TestContextManager.java:269)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

It looks like Wiremock is trying to load our response body file as a stub mapping using the JSON API when in reality we're using .withBodyFile("product-catalog-response.json") in the wiremock server configuration. If we remove the wiremock starter and use just vanilla wiremock it works fine as we have our files in the default location (__files).

mduesterhoeft commented 6 years ago

Does the folder contain stub files and response/request body files? It looks like WireMock is parsing a body file as a stub file and fails deserializing it.

In all the cases I tested the body was part of the stub file (inline body). Can you share a sample project to share so I could have a closer look myself?

When recording stub with external body files I have seen that WireMock stores the stubs in a mappings directory and the body files to __files.

So you could try to have

Then use WireMockTest like this:

@WireMockTest(stubPath = "stubs")