I'm trying to develop some test file for a Neo4j project. I have found that Neo4j provides JUnit Rule (http://neo4j.com/docs/stable/server-unmanaged-extensions-testing.html) and I have try to use it for testing. However, it does not work as intendant.
My code is exactly as in the Neo4j help page:
#Rule
public Neo4jRule neo4j = new Neo4jRule()
.withFixture( "CREATE (admin:Admin)" )
.withFixture( new Function<GraphDatabaseService, Void>()
{
#Override
public Void apply( GraphDatabaseService graphDatabaseService ) throws RuntimeException
{
try (Transaction tx = graphDatabaseService.beginTx())
{
graphDatabaseService.createNode( DynamicLabel.label( "Admin" ));
tx.success();
}
return null;
}
} );
#Test
public void shouldWorkWithServer() throws Exception
{
// Given
URI serverURI = neo4j.httpURI();
// When I access the server
HTTP.Response response = HTTP.GET( serverURI.toString() );
// Then it should reply
assertEquals(200, response.status());
}
I'm receiving this error:
Failed tests: shouldWorkWithServer(test.Test): expected:<200> but was:<500>
I have try to resolve 'db/data/' path:
URI serverURI = neo4j.httpURI().resolve("db/data/");
The result has been same. I have also try to use TestServerBuilders instead and generate Http Authentication header with default 'neo4j:neo4j' and have got same error again. The server does created, I can access to it via getGraphDatabaseService() and see the nodes, but I can not access it via HTTP.
The Neo4j version is 3.2.1 and the JUnit version is 4.11
If using Maven, do not forget that the order you declare the dependencies has an importance. Therefore, you should declare the "provided" dependencies after the "test" ones, so the implementation of the test library is used prior to the provided one. That is good practice for all the JEE related libraries.
In your case, make sure you declare javax.ws.rs:javax.ws.rs-api:2.0 after org.neo4j.test:neo4j-harness:2.3.1
Related
I am using Jhipster(Angular + Springboot) Application for my existing project.
I managed to create a controller(app.resource) manually apart from the ones already generated by jhiptser(using .jh file) for achieving a file download functionality.
So, when we start the server we usually initiate two servers i.e gradlew and npm start. The second runs on port 9000 which eventually supports hot reload functionality.(front-end development)
So the problem is, I am able to access those endpoints from the server running on standard 8000 port. However, from the port which is a proxy(9000), the method is returning 404.
I tried to clean build the application several times.
NOTE: The #RequestMapping value on the new controller is different then those present already.
Does this have to do something with spring security?
Thanks in advance.
Here is the previous controller:
#RestController
#RequestMapping("/api")
public class FGAppDiagramResource {
#GetMapping(value = "/fg-app-diagram-downloadFile")
public void getImage(String fileName,String folderName, HttpServletResponse
response){
// Some Code
}
}
Here is my New controller:
#RestController
#RequestMapping("/fileDownload")
public class DownloadFileController {
private final Logger log =
LoggerFactory.getLogger(DownloadFileController.class);
public DownloadFileController() {
super();
}
#Autowired
private ApplicationProperties applicationProperties;
#GetMapping(value = "/fg-app-diagram-downloadFile/{fileName}/{folderName}")
public void getImage(#PathVariable String fileName,#PathVariable String folderName, HttpServletResponse response) {
// Some Code
}
}
Your new controller does not use /api so you must add your endpoint URL /fileDownload to proxy configuration of webpack dev server in webpack/webpack.dev.js
proxy: [{
context: [
/* jhipster-needle-add-entity-to-webpack - JHipster will add entity api paths here */
'/api',
'/fileDownload',
You may want to use /api/fileDownload to avoid changing proxy configuration and also because /api is useful for many other aspects like security and also using HTML5 URL routing strategy in Angular to get rid of # in client routes (see https://github.com/jhipster/generator-jhipster/pull/9098).
/api and /management are namespaces to avoid route conflicts, so it is usually wise to use them for your new endpoints.
Suppose the application is dependent on a REST service on a external server, http://otherserver.com. For testing, I would like to simulate the external rest call (via Wiremock) within a JUnit environment. Starting a seperate server consumes time and is not easy. Working with WiremockRule looks the right direction. Creating simulation controllers is not an elegant way as Wiremock is available.
E.g. get( "http://otherserver.com/service3/");
PS: of course I know that I can simulate a REST call via Mockito.
Simulating localhost with Wiremock is easy. How can I use that code to simulate other servers and services? I copied parts from the popular Baeldung examples.
public class WireMockDemo {
#Rule
public WireMockRule wireMockRule = new WireMockRule();
#Test
public void wireMockTestJunitOtherServer() {
try {
// **this does not work...**
configureFor("otherserver.com", 8080);
stubFor(get(urlPathMatching("/service2/.*"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody("\"testing-library\": \"WireMock\"")));
// Test via simple client
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet request = new HttpGet("http://otherserver:8080/service2/test");
HttpResponse httpResponse = httpClient.execute(request);
String stringResponse = convertHttpResponseToString(httpResponse);
System.out.println( "Response = " + stringResponse);
// Test via JUnit
verify(getRequestedFor(urlEqualTo("/service2/wiremock")));
assertEquals(200, httpResponse.getStatusLine().getStatusCode());
assertEquals("application/json", httpResponse.getFirstHeader("Content-Type").getValue());
assertEquals("\"testing-library\": \"WireMock\"", stringResponse);
} catch( Exception e) {
e.printStackTrace();
}
}
// Support methods
private String convertHttpResponseToString(HttpResponse httpResponse) throws IOException {
InputStream inputStream = httpResponse.getEntity().getContent();
return convertInputStreamToString(inputStream);
}
private String convertInputStreamToString(InputStream inputStream) {
Scanner scanner = new Scanner(inputStream, "UTF-8");
String string = scanner.useDelimiter("\\Z").next();
scanner.close();
return string;
}
}
Your application code should not have the http://otherserver.com hardcoded, it should be configurable. When running normally it should point to http://otherserver.com, when running in test mode it should be pointed to http://localhost:<port> where <port> is where you have started your Wiremock server (preferably dynamic to avoid port clashes)
TL; DR:
No, you cannot.
What WireMock does, is to establish a Jetty server simulating a remote server you need to send request to. However, it does not change your hosts file or DNS mapping and automatically "redirect" your real request for remote server to localhost. In tests you still need to send request to localhost.
What you can do, if you are using Spring Boot, is to create two application.yml file(or another properties file) in main and test package, with same structure of keys, but the value in src/main/resources/application.yml is the real URL you request(like http://example.com/api), and that in src/test/resources/application.yml you put localhost/api.
By the way, to clarify, MockMvc is not for simulation of external 3rd party server request that your application depends on, but requests sent to the endpoints of your application. In MockMvc tests, your application is who receives the request, but in WireMock tests, your applications sends request.
Some working example:
// configure static, class-level rule for all tests, like #BeforeClass.
// this launches a Jetty server with configurations
#ClassRule
public static WireMockClassRule classRule = new WireMockClassRule(options().
port(80).httpsPort(443));
// Divide #ClassRule and #Rule,
// to bypass JUnit limitation of "#Rule cannot be static"
#Rule
public WireMockClassRule rule = classRule;
#Test
public void shouldReturnGivenJson() throws Exception {
// stubFor() also works; givenThat() is more TDD-ish
givenThat(post(urlEqualTo("/service2/test")) // <----- note here: without host name
.willReturn(WireMock.aResponse()
.withStatus(HttpStatus.OK.value())
.withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE)
.withBody("{\"status\":\"up\"}")));
// .... your connection here
I suggest to begin with urlEqualTo(), without messing around with regex. Then you progress to urlMatching().
Also, use org.apache.http.util.EntityUtils to get content from the response. This is the official, built-in way to process the response. And, use a ResponseHandler because it will consume() the response without manually cleaning the resources.
Check HttpClient documentation for more details.
I am current building a JAX-RS client using Apache CXF version 3.1.11. I have been looking at some simple examples online and it appears the WebClient class has gone missing.
See the example code below that I found online.
public static void main(String[] args) throws JsonParseException,
JsonMappingException, IOException {
WebClient client = WebClient
.create("http://localhost:8080/",
Collections.singletonList(new JacksonJsonProvider()))
.path("test").accept(MediaType.APPLICATION_JSON_TYPE);
Message message = client.get(Message.class);
System.out.println("Message recieved : " + message);
}
I cannot find the WebClient class anywhere in the code and im using the following maven dependencies.
cxf-rt-frontend-jaxws
cxf-rt-transports-http
cxf-rt-transports-http-jetty
Please could someone confirm if I am missing a dependency or if WebClient has been removed from version 3.1.11
If you're not sure about specific provider implementation, you can use classes which are standar parts of JAX-RS instead, which are duo Client and WebTarget. But for marshalling things, sure, you probably still need specific dependency configured, either manually or it's been already provided by the Apache CXF.
Client client = ClientBuilder.newBuilder().build();
WebTarget target = client
.target("http://localhost:8080/");
Response response = target.request().get();
Message message = client.readEntity(Message.class);
/*
// now.. process the message
for (Message message : message.get...) {.. }
*/
response.close(); // close connections.
You need to add cxf-rt-frontend-jaxrs instead of cxf-rt-frontend-jaxws
Since I want to use the RestTemplate from Spring I want to use the same class as well for Unit-Testing. The idea would be to download a JSON-File and save it locally for the purpose of testing. Therefore I would like to change the URI from a HTTP to a File address. When it as File-address I get an Excpetion
Exception in thread "main" java.lang.IllegalArgumentException: Object of class [sun.net.www.protocol.file.FileURLConnection] must be an instance of class java.net.HttpURLConnection
urlGETList = "http://api.geonames.org/countryInfoJSON?username=volodiaL";
RestTemplate restTemplate = new RestTemplate();
CountryInfoResponse results = restTemplate.getForObject(urlGETList, CountryInfoResponse.class);
Any ideas how I can use the same classes for Unit-Testing?
I think you could look into Wiremock.
Wiremock allows subbing of requests. The advantage is that you really test the complete stack and your tests make real requests against a server responding with mock responses. These mock response bodies can be files (there are other possibilities as well.)
In your unit test you set up wiremock server like this:
#Rule
public WireMockRule wireMockRule = new WireMockRule(port);
Then you can setup a stub with a file response like this:
public void givenResponse(int statusCode, MediaType contentType, String bodyPath) {
String responseBody;
try (InputStream data = new ClassPathResource(bodyPath).getInputStream()) {
responseBody = copyToString(data, UTF_8);
}
stubFor(any(urlPathEqualTo(getWireMockUri().getPath()))
.willReturn(aResponse()
.withStatus(statusCode)
.withHeader("Content-Type", contentType.toString())
.withHeader("Content-Length", String.valueOf(responseBody.length()))
.withBody(responseBody)
));
}
You could also put the complete stub into a stub file like described here
Afterwards you can check if a certain request has been made:
verify(postRequestedFor(urlEqualTo("/form"))
.withHeader("Content-Type", containing(MULTIPART_FORM_DATA_VALUE)));
You can find out more about verification here
You would use the RestTemplate to make requests. You just need to have host and port configurable so you can use localhost and the wiremock port in your tests.
the my web-app working fine in eclipse and the Netbeas but when i try to execute in maven after include the dependency its throwing exception.The dependency is.
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-bundle-jaxrs</artifactId>
<version>2.1.2</version>
</dependency>
This dependency i include because i am using the
ResponseBuilderImpl builder = new ResponseBuilderImpl()
if i remove the builder and dependency then its work in maven but when i included then its giving exception.this is my rest sample rest code.
#Path("/{userId}/logout")
#PUT
public Response logout(#PathParam ("userId") String userId,#Context HttpServletRequest request,#Context HttpServletResponse response)throws ServletException, IOException
{
ResponseBuilderImpl builder = new ResponseBuilderImpl();
log.debug("request user id for logout::"+userId);
MapUserLogin mapUserLogin=new MapUserLogin();
mapUserLogin.removeMap(userId);
log.debug("after remove userinformation from hashmap");
System.out.print("LOGOUT SUCCESSFULLUY");
builder.status(200).entity("SUCCESS");
return builder.build();
}
so for the ResponseBuilderImpl i imported the import org.apache.cxf.jaxrs.impl.ResponseBuilderImpl
if i remove and just return string types then its work but when i am using this above code then only maven is throwing exception The exception is.
INFO: Deployed Application(path=C:\App\apache-tomee-jaxrs-1.5.2\webapps\Snefocaremaven)
Oct 01, 2013 10:51:10 AM org.apache.openejb.observer.ObserverManager fireEvent
SEVERE: error invoking org.apache.openejb.observer.ObserverManager$Observer#21d4f61d
java.lang.reflect.InvocationTargetException
Unless you have a good reason to use the CXF-specific ResponseBuilderImpl you should use the static factory methods of the JAX-RS Response class to obtain a ResponseBuilder, e.g.
Response response = Response.status(200).entity("SUCCESS").build();
The JAX-RS framework will use an internal mechanism to load and initialize the correct implementation. Note that you should not need the CXF dependency at compile time, unless you are using proprietary features.
update:
ResponseBuilder partial = Response.status(200);
Will create a mutable builder instance, which can be further modified. Note that you should also be able to modify the status on the builder. Unfortunately (?) there is no "plain" factory method available from the JAX-RS API. I would suggest to first try out the creation of a Response this way and check, whether it works or if there are more subtle problems.
ResponseBuilder partial = Response.status(200); // mock status
ResponseBuilder filled = fillResponse(partial); // whatever the method is called
return filled.build();
Then you can think about refactoring to get rid of the creation of the builder with a mock status, for example by moving the whole response building into a method that knows the entity and response code.