Azure Trigger Function Integration Test With Wiremock - java

I have an Azure TimerTrigger running (fully functional) with spring boot and am running into an issue running an integration test. Below is what my function looks like.
When I use mvn azure-functions:run I am able to hit http://localhost:7071/admin/functions/myTrigger as defined in the docs
#FunctionName("myTrigger")
public void execute(
#TimerTrigger(name = "timerInfo", schedule = "%myCronSetting%") String timerInfo,
final ExecutionContext context
) {
handleRequest(timerInfo, context);
}
However, I always get 404 responses when running my integration test using wiremock
when().post("/admin/functions/myTrigger").then().log().body().statusCode(202);
I suspect the function itself isn't starting up with spring when running the integration test but that's just a guess. I'm not quite sure how to proceed. I have seen other related answers with C# where they have code to trigger the function inside their test but I cannot find a way to do that in java (nor do I know it that's even possible)

Related

How to get wiremock running before the spring boot application status up?

I have an integration test for a spring boot micro-service. The problem is that the service calls an external service (via REST) on startup. I’m using WireMock to mock the call. Spring makes the application start before WireMock is started. Because of this, the rest call fails and so does the service.
The call is made by a library that is also made by our company, so I cannot change anything there.
Do you have any suggestions for me?
you might create static instance of WireMockServer in your test. Here is a code sample:
#RunWith(SpringRunner.class)
#SpringBootTest
public class YourApplicationTests {
static WireMockServer mockHttpServer = new WireMockServer(10000); // endpoint port here
#BeforeClass
public static void setup() throws Exception {
mockHttpServer.stubFor(get(urlPathMatching("/")).willReturn(aResponse().withBody("test").withStatus(200)));
mockHttpServer.start();
}
#AfterClass
public static void teardown() throws Exception {
mockHttpServer.stop();
}
#Test
public void someTest() throws Exception {
// your test code here
}
}
The Spring Boot team have built a WireMock integration. Might be worth checking it out rather than rolling your own: http://cloud.spring.io/spring-cloud-static/spring-cloud-contract/1.1.2.RELEASE/#_spring_cloud_contract_wiremock
I'm late to the party here, but I've been struggling with the same thing several times, and while the accepted answer can work in many cases, here's the solution I came up with:
https://github.com/ThomasKasene/wiremock-junit-extension
It's a custom JUnit Jupiter extension that you put over your test class, and it'll start up the server for you, much like Spring Cloud Contract's version. The difference is that it's detached from the Spring context so it can be started before Spring spins up its context.
If you are running Wiremock programmatically inside JUnit tests you might run into race condition since start() is non blocking. Check official documentation here it states that in context of JUnit tests:
For JUnit 4.x and JUnit 5 Vintage you should use JUnit rule included
in WireMock
For JUnit 5+ Jupiter use JUnit Jupiter extension
In my case, the static config was working locally and in our CI, until we migrated our CI to cloud.. for some reason, one test was failing, because one Spring bean initiates its cache at startup by calling a remote service, and wiremock was not available at that time.. so the cache would be empty.
why did this start to happen ? I have no idea.. but after adding more logs, to track when the Spring bean was getting instantiated vs when Wiremock was being setup, I realized that the Spring beans were being reused from a previous test.
so my solution, in addition to the static config, was to add #DirtiesContext(classMode = ClassMode.BEFORE_CLASS) on my test, to make sure that the whole Spring context ws being reloaded before running the tests

How to use multi thread to start a web app before I run test cases for this target web?

Hi I am working on integration tests for a web application and I am using TestNG and Maven. I made a test suite including all my test cases. In order to start the web app before all tests running, I start the web application in the #BeforeSuite annotated method as this:
#BeforeSuite
public void prepareTestContext() {
ConfigServer.main(); //This is a spring boot web app.
}
Now I want to start this web application in a another thread, I am new to multi threading programing, could anyone please tell me how should I get this done with another thread? Thanks.
use this :
#BeforeSuite
public void prepareTestContext() {
new Thread(new Runnable() {
#Override
public void run() {
ConfigServer.main();
}
},"web-app-runner").start();
}
Generally, when running tests like this in Maven, use the integration-test phase with Failsafe. In the pre-integration-test phase, you set up whatever environment is necessary, including starting up the application (maybe a Docker container with a test database, too), then run tests in integration-test, then shut down your test context in post-integration-test.
With Spring Boot, however, all of this functionality is already supported by Boot itself, including features like the ability to only start up the "slice" of your application actually needed for a test. Take a look at the #SpringBootTest annotation and the Spring blog article on the latest test enhancements.

Writing Java/Maven integration tests using webservice database and jms

I'm maintaining a Java Enterprise Application that exposes a few webservices and interacts with a few JMS queues and a database.
I've got most of the code unit tested and I thought all was good until in a refactoring I moved a class in another package and that changed a namespace in my webservice without me noticing and breaking all clients.
An Integration Test would have caught that, so I'm trying to write one.
The application is deployed on JBoss EAP 6.4, how can I make a webservice call in my mvn verify step?
What about JMS Queues? They are configured on the Application Server.
Is the application supposed to be already deployed?
Am I supposed to deploy the application with maven to a JBoss installation before the verify step or start an embedded webserver?
Most of the docs around are confusing to me and often I see suggestion to mock stuff, which is not integration testing (and I already do in Unit tests).
Someone told me "just use Jenkins" and I read the docs, installed it and still don't understand how that is supposed to help me write integration tests since all it does is run mvn verify anyway.
This topic and is too broad, there might be many different correct answers for this question and will depend a lot on the technologies you're using, so I'll focus first in this part only:
that changed a namespace in my webservice without me noticing and
breaking all clients
You can create unit tests for endpoints too, I do that all the time with spring-boot. For example, the code below starts the application, runs the testEndpoint() test and shuts down the application right after.
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = {MyApplication.class})
#WebAppConfiguration
#IntegrationTest("server.port:0")
public class MyControllerTest {
#Value("${local.server.port}")
private int port;
#Test
public void testEndpoint() {
String endpointUrl = "http://localhost:" + port;
// make a HTTP request here to test the endpoint
}
}
I believe this can be done with any spring-mvc application, but the code would be a bit different and not as easy as with spring-boot.
Although this would usually catch most bugs in endpoints, it doesn't eliminate the need of integration tests against a deployed project.
So focusing on the bigger picture now, if you want to create end-to-end tests, including WebServices, JMS queues and databases, I suggest creating a separate project with tests only, probably using Cucumber or something similar. This project should be triggered in Jenkins (or any other CI tool) whenever needed (e.g. before a deployment, every hour, every commit and/or every night) and it will require that all applications are already deployed.
Alternatively, you could have Jenkins deploy an application and run integration tests only against this one application. In this case the tests will depend on all other applications to be already deployed.

Amazon Kinesis + Integration Tests

I'm currently working on a series of web-services which we need to integrate with Kinesis - the implementation has been done, however we have a series of integration tests (our web-services are all using Spring Boot so we use the #WebIntegrationTest annotation on our test classes to start up a local instance of the server and then call our resources with a TestRestTemplate) which are currently trying and failing to connect to the real Kinesis.
Although in ordinary unit tests it's not a problem to mock out calls to the methods within the Kinesis library, we can't really do this in the integration tests as the whole application stack is wired up with Spring. For a few other things (such as OAuth2 and calls to our other web-services) we've been able to use WireMock to mock out the actual endpoints - what I'd really like to do is use WireMock in this fashion to mock out the call to the AmazonKinesisClient but I can't find any advice on how to do this.
Alternatively I have seen that some AWS components have test libraries written by third parties which allow you to run a local version of it (e.g.: DynamoDbLocal) but can't find such a solution for Kinesis.
Is anyone able to give me some advice on how to run integration tests with Kinesis?
It might already be too late to give the solution but I will add what my team has done to replicate AWS resources locally as we use a lot of Kinesis, DynamoDb, S3 and cloudWatch.
We have created wrappers around Localstack -> https://github.com/localstack/localstack that allow us to spin up local instances of the necessary services as docker containers using docker-compose.
A typical docker-compose.yml file for us looks like:
version: '2'
services:
localstack:
image: "localstack/localstack"
environment:
- SERVICES=kinesis,dynamodb,cloudwatch
ports:
- "4568"
- "4569"
- "4582"
Then during the setup phase for the integration-tests, our wrapper fires up docker-compose up and runs the tests against the local infrastructure.
Later during tear-down, the wrapper kills the containers.
I ran into the same issue and the only mock implementation I found so far was a nodejs one: https://github.com/mhart/kinesalite
It does the trick - I managed to run my Java Kinesis client against it, just had to set the endpoint on the kinesis.properties:
kinesisEndpoint=http://localhost:4567
The downside is that it is not trivial to use it during build time tests - need to figure a way to start the mock kinesis before the test (using a maven plugin or something), didn't get to it yet..
Just a small addition to the existing answers. BTW, they are great, you should really use tools like localstack to start fake AWS services before the test during the test phase.
If you're using JUnit 5 in your tests, your life could be even simpler with JUnit 5 extensions for AWS, a few JUnit 5 extensions that could be useful for testing AWS-related code. These extensions can be used to inject clients for AWS service mocks provided by tools like localstack. Both AWS Java SDK v 2.x and v 1.x are supported:
#ExtendWith(DynamoDB.class)
class AmazonDynamoDBInjectionTest {
#AWSClient(
endpoint = Endpoint.class
)
private AmazonDynamoDB client;
#Test
void test() throws Exception {
Assertions.assertNotNull(client);
Assertions.assertEquals(
Collections.singletonList("table"),
client.listTables().getTableNames().stream().sorted().collect(Collectors.toList())
);
}
}
Here, client will be just injected in your test class and configured according to the Endpoint configuration class.

What is the best way to write a test case for JERSEY web services?

I have a JAX-RS web service implemented with Jersey library and now I want to test it. In order to do that I'd like to host this service in my test by preinitializing it with mocked services.
What is the best way to host such a service and execute the test calls?
#Path("/srv")
public class MyService
{
#GET
public void action(#Context UriInfo uri)
{ ... }
}
#Test
public void myTest()
{
MyService service = new MyService();
service.setSomething(...);
// How do I host it?
// How do I call it?
}
The new (revised) Jersey Test Framework which is part of the Jersey 1.1.2-ea release now supports the In-Process or In-Memory testing. In order to run your tests in-memory all you have to do is set the property test.containerFactory to com.sun.jersey.test.framework.spi.container.inmemory.InMemoryTestContainerFactory, i.e., run your tests as follows:
mvn clean test -Dtest.containerFactory=com.sun.jersey.test.framework.spi.container.inmemory.InMemoryTestContainerFactory -DenableLogging
For more details please go through the blog entry titled Jersey Test Framework re-visited! at http://blogs.oracle.com/naresh.
I believe the Jersey Test Framework provides a solution for your requirement. It allows you to deploy a single service, and run all its tests. You could use the framework to run your tests against Grizzly Web Container, Embedded GlassFish and/or HTTPServer.
Please note that you could use the framework to run your tests against the regular web containers like GlassFish and Tomcat too. In case you have any more queries please feel free to send me or the Jersey users mailing list - users#jersey.dev.java.net an e-mail.
I haven't tried it, but a JUnit extension like HtmlUnit or HttpUnit may be a good way to test a JAX-RS/Jersey service. The test case can use XPaths to find expected return values and validate the returned value against the expected. See: http://htmlunit.sourceforge.net/gettingStarted.html for more info.
You can use Grizzly to host the services and then use the Jersey Client to access them. Take a look at the sample applications. For example, in the Bookstore sample you may find the TestSupport class and JerseyTest class (found in the jersey-test-framework) of particular interest.
I hope this helps.
(Unfortunately Stack Overflow wouldn't let me post until I removed all the hyperlinks so happy Googling!).
Okay I get it now. Right now the framework doesn't support IN PROCESS, bt we are working on it.
We will see that this support would be added in a coming version of the Jersey Test Framework
Have you looked in to using the Jersey Test Framework? Unfortunately it's still more integration test than unit test, but it might get you on your way.

Categories

Resources