Search code examples
jboss-arquillianshrinkwrap

Arquillian ShrinkWrap how to add an asset to the file system path


I am importing a library that reads from the file system instead of my web archive's resource folder. I want to be able to essentially mock that file by adding an asset with that path using ShrinkWrap, so I can run tests on my build server without guaranteeing the file system has all these files. I tried to add a String Asset in the appropriate path, but the code can't find that asset. Here's an example of what I'm trying to achieve.

Rest Resource

@Path("/hello-world")
public class HelloWorldResource {

    @GET
    public Response getHelloWorld(){
        return Response.ok(getFileContent()).build();
    }

    private String getFileContent() {

        StringBuilder builder = new StringBuilder();
        try {
            BufferedReader bufferedReader = new BufferedReader(
                    new FileReader(
                            "/usr/myFile.txt"));
            String line = bufferedReader.readLine();
            while (line != null) {
                builder.append(line);
                line = bufferedReader.readLine();
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return builder.toString();
    }
}

Test

@RunWith(Arquillian.class)
public class HelloWorldResourceTest {

    @Deployment
    public static WebArchive createDeployment()
    {
        WebArchive webArchive = ShrinkWrap
                .create(WebArchive.class)
                .addPackages(true,
                        HelloWorldApplication.class.getPackage(),
                        HelloWorldResource.class.getPackage(),
                        Hello.class.getPackage())
                .add(new StringAsset("Blah"),"/usr/myFile.txt")
                .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
        System.out.println("WebArchive: " + webArchive.toString(true));
        return webArchive;
    }

    @Test
    @RunAsClient
    public void testHello(
            @ArquillianResteasyResource("hello-world") final WebTarget webTarget)
    {
        final Response response = webTarget
                .request(MediaType.APPLICATION_JSON)
                .get();
        String hello = response.readEntity(String.class);
        System.err.println("Hello: " + hello);

        Assert.assertEquals("Status is not OK", response.getStatus(), 200);
    }
}

Web Archive toString

/WEB-INF/
/WEB-INF/classes/
/WEB-INF/classes/com/
/WEB-INF/classes/com/
/WEB-INF/classes/com/
/WEB-INF/classes/com/helloworld/
/WEB-INF/classes/com/helloworld/application/
/WEB-INF/classes/com/helloworld/application/HelloWorldApplication.class
/WEB-INF/classes/com/helloworld/resource/
/WEB-INF/classes/com/helloworld/resource/HelloWorldResourceTest.class
/WEB-INF/classes/com/helloworld/resource/HelloWorldResource.class
/WEB-INF/classes/com/helloworld/dataobjects/
/WEB-INF/classes/com/helloworld/dataobjects/Hello.class
/WEB-INF/beans.xml
/usr/
/usr/myFile.txt

I get the following error:

java.io.FileNotFoundException: /usr/myFile.txt (No such file or directory)

Seems like ShrinkWrap is adding /usr/myFile.txt as a relative path within the archive instead of making it seem like /usr/myFile.txt is at the root directory of my file system. Is there any way I can get ShrinkWrap to do what I want?


Solution

  • Shrinkwrap is intended to create archives, so the API is scoped to create assets within the archive you are creating. If you want to have resources created in the regular filesystem simply use JDK, there is nothing Shrinkwrap could help you with.

    Alternatively, if possible, change your resource to read resources from the classpath, not filesystem path. With this approach, you can easily swap content for the test using Shrinkwrap as you are trying now with your example.