I'm trying to create an Azure Function written in Java and configured using a function.json file (rather than using annotations).
To get started I followed the MS tutorial (which works ok).
Next, I tried to modify the class to remove the Function annotations and add a function.json as indicated here in the section "The same function written without annotations".
The class source code is now:
public class Function {
public static String hello(String req, ExecutionContext context) {
return String.format("Hi, %s!", req);
}
}
My function.json file is
{
"scriptFile": "ServiceBusQueueMsgToLogWriter-1.0-SNAPSHOT.jar",
"entryPoint": "com.oneadvanced.adv365.mgdsvc.azure.func.test1.Function.hello",
"bindings": [
{
"type": "httpTrigger",
"name": "req",
"direction": "in",
"authLevel": "anonymous",
"methods": [ "post" ]
},
{
"type": "http",
"name": "$return",
"direction": "out"
}
]
}
The output of running the command:
mvn clean package
Includes the output:
AI: INFO 12-10-2017 21:50, 1: Configuration file has been successfully found as resource
AI: INFO 12-10-2017 21:51, 1: Configuration file has been successfully found as resource
[INFO]
[INFO] Step 1 of 6: Searching for Azure Function entry points
[INFO] Reflections took 33 ms to scan 1 urls, producing 0 keys and 0 values
[INFO] 0 Azure Function entry point(s) found.
[INFO]
[INFO] Step 2 of 6: Generating Azure Function configurations
[INFO] No Azure Functions found. Skip configuration generation.
This makes me wonder if the function.json file isn't in the right place...
Does anyone know where the correct place to put the function.json file for an Azure Function written in Java?
I've tried:
in the root of the project
in src/main/resources (which I think would be the standard place for this kind of thing in a typical Java/Maven project)
in the same folder as the Java source file
Same outcome in every case :(
I'd be grateful for any pointers on what I should be doing.
Thanks, Andy
The code for all of the functions in a given function app lives in a
root folder that contains a host configuration file and one or more
subfolders, each of which contain the code for a separate function.
Example Structure:
wwwroot
| - host.json
| - mynodefunction
| | - function.json
| | - index.js
| | - node_modules
| | | - ... packages ...
| | - package.json
| - mycsharpfunction
| | - function.json
| | - run.csx
You could find the description above from official doc.
However,I notice that your function.json file doesn't set disabled property.
Set the disabled property to false to enable the function which is mentioned here.
{
"bindings": [
{
"name": "myBlob",
"type": "blobTrigger",
"direction": "in",
"path": "jaygong/test",
"connection": "AzureWebJobsStorage"
}
],
"disabled": false
}
Update Answer:
I tried to create my own azure function with the steps you provided by configuring function.json and I reproduced your issue!
My function code:
package cn.gjj;
public class Function {
public static String hello(String in) {
return in;
}
}
My function test code:
package cn.gjj;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* Unit test for Function class.
*/
public class FunctionTest {
/**
* Unit test for hello method.
*/
#Test
public void testHello() throws Exception {
final Function function = new Function();
final String ret = function.hello("function");
assertEquals("function", ret);
}
}
My function.json file:
{
"scriptFile": "JayGongTestAzureFunction-1.0-SNAPSHOT.jar",
"entryPoint": "cn.gjj.Function.echo",
"bindings": [
{
"type": "httpTrigger",
"name": "req",
"direction": "in",
"authLevel": "anonymous",
"methods": [ "post" ]
},
{
"type": "http",
"name": "$return",
"direction": "out"
}
]
}
When I run the command mvn clean package, the log shows as same as you.
AI: INFO 17-10-2017 14:07, 1: Configuration file has been successfully found as resource
AI: INFO 17-10-2017 14:07, 1: Configuration file has been successfully found as resource
[INFO]
[INFO] Step 1 of 6: Searching for Azure Function entry points
[INFO] Reflections took 31 ms to scan 1 urls, producing 0 keys and 0 values
[INFO] 0 Azure Function entry point(s) found.
[INFO]
[INFO] Step 2 of 6: Generating Azure Function configurations
[INFO] No Azure Functions found. Skip configuration generation.
[INFO]
[INFO] Step 3 of 6: Validating generated configurations
[INFO] No configurations found. Skip validation.
[INFO]
[INFO] Step 4 of 6: Saving empty host.json
[INFO] Successfully saved to E:\TestAzureFunction\JayGongTestAzureFunction\target\azure-functions\jaygongtestazurefunction-20171017132623892\host.json
[INFO]
[INFO] Step 5 of 6: Saving configurations to function.json
[INFO] No configurations found. Skip save.
[INFO]
[INFO] Step 6 of 6: Copying JARs to staging directory E:\TestAzureFunction\JayGongTestAzureFunction\target\azure-functions\jaygongtestazurefunction-20171017132623892
After careful comparison of function.json configuration way and annotations way, I found directories of Project/target/azure-functions/functionName/ folder are different.
annotations way:
function.json configuration way:
Note that if the function.json file is not found after mvn compile,please add the key line below in your pom.xml file.
<resources>
<resource>
<directory>${project.basedir}</directory>
<includes>
<include>host.json</include>
<include>local.settings.json</include>
**<include>function.json</include>**
</includes>
</resource>
</resources>
Solution:
Create a job folder and move your function.json file into it.Then it works for me.
Please give it a try.
Hope it helps you.
Related
I am not able to read test data from outside the src folder of project using java code. I am using bazel for testing java code.
The project hierarchy is as below:
Parent
Project1
Project2
Project3
Subproject1
Subproject2
data
Subfolder
Xyzzy.spi
Xyzzy.spl
BUILD.bazel
Src/main/java
Src/test/java
Com.test.sometest
Test1.java
Test2.java
BUILD.bazel
data/subfolder/BUILD.bazel:
exports_files(["Xyzzy.spi", "Xyzzy.spl"])
src/test/java/Com/test/sometest/BUILD.bazel:
load(
"//bazel:defs.bzl",
"java_library",
"java_test",
"java_binary",
)
java_test(
name = “subproject2”,
test_library = "subproject2_lib",
)
java_binary(
name = "example",
data = [
“//project3/subproject2/data/subfolder: Xyzzy.spi",
“//project3/subproject2/data/subfolder: Xyzzy.spl”,
],
runtime_deps = [":subproject2_lib"],
)
java_library(
name = "subproject2_lib",
testonly = True,
srcs = glob(
[
"*.java",
],
),
deps = [
"//:lombok",
“Path to point to build bazel of main java code”,
"#maven//:com_google_guava_guava",
"#maven//:commons_io_commons_io",
"#bazel_tools//tools/java/runfiles:runfiles",
"#maven//:junit_junit",
],
)
And java code to get path to file:
private static File CURRENT_INDEX_FILE=Paths.get("data/subfolder/Xyzzy.spi").toFile();
I am getting FileNotFoundException when running bazel test. Not sure where am doing it wrong. I tried google about this but no similar cases i found, mostly they have Maven Standard hierarchy but what should i change for this folder structure to work with.
Thanks
I have the following Scenario Outline
#Example
Scenario Outline:
Given that I have gone to the Google page
When I add <animal> to the search box
And click the Search Button
Then "<term>" should be mentioned in the results
Examples:
| animal | term |
| cat | cat |
| dog | dog |
Step definition class has
#Given("^that I have gone to the Google page$")
public void that_I_have_gone_to_the_Google_page() {
Launch.launch();
}
#When("I add {string} to the search box")
public void i_add_to_the_search_box(String arg1) throws Throwable {
GoogleHomePage hPage = new GoogleHomePage(driver, dataMap);
hPage.performGoogleSearch(arg1);
}
#And("^click the Search Button$")
public void click_the_Search_Button() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
#Then("^\"([^\"]*)\" should be mentioned in the results")
public void should_be_mentioned_in_the_results(String resultTerm) {
GoogleResultPage grPage = new GoogleResultPage(driver, dataMap);
grPage.verifyResult(resultTerm);
}
And the execution has
#Example #GoogleSearch
Scenario Outline: # google/searchTerm.feature:17
Given that I have gone to the Google page # GoogleSearchSD.that_I_have_gone_to_the_Google_page()
When I add cat to the search box
And click the Search Button # GoogleSearchSD.click_the_Search_Button()
Then "cat" should be mentioned in the results # GoogleSearchSD.should_be_mentioned_in_the_results(String)
#Example #GoogleSearch
Scenario Outline: # google/searchTerm.feature:18
Given that I have gone to the Google page # GoogleSearchSD.that_I_have_gone_to_the_Google_page()
When I add dog to the search box
And click the Search Button # GoogleSearchSD.click_the_Search_Button()
Then "dog" should be mentioned in the results # GoogleSearchSD.should_be_mentioned_in_the_results(String)
2 Scenarios (2 undefined)
8 Steps (4 skipped, 2 undefined, 2 passed)
So you see that all the steps but the When are recognized/matched up.
The When statement/code isn't being executed, hence the rest of the code is being skipped.
I have copied and pasted the suggested code snipe of the missing step. Not that it helps.
Versions I have in Eclipse Plug-in Registry:
cucumber.eclipse.backends.java (1.0.0.202106240526) "Cucumber Java
Backend" [Active]
cucumber.eclipse.editor (1.0.0.202106240526)
"Cucumber Editor" [Active]
cucumber.eclipse.steps.integration
(1.0.0.202106240526) "Cucumber Steps Integration" [Active]
cucumber.eclipse.steps.jdt (1.0.0.202106240526) "Cucumber Steps via
Eclipse JDT" [Active]
org.agileware.natural.cucumber (1.3.6.202005221158) "org.agileware.natural.cucumber" [Active]
org.agileware.natural.cucumber.ui (1.3.6.202005221158) "org.agileware.natural.cucumber.ui" [Active]
Update 7/15/2021, 5:00 PM EDT
Just to see what would happen, I changed the Scenario Outline
And I add "<animal>" to the search box
When click the Search Button
and the former When statement works as an And, but the previous And doesn't work as a When.
So it does seem to be the actual When statement, and not what the statement is.
>mvn dependency:list | findstr cucumber
[INFO] -------------< org.cucumber.example:org.cucumber.example >--------------
[INFO] --- maven-dependency-plugin:2.8:list (default-cli) # org.cucumber.example ---
[INFO] com.github.mkolisnyk:cucumber-runner:jar:1.3.5:test
[INFO] io.cucumber:html-formatter:jar:13.0.0:compile
[INFO] io.cucumber:docstring:jar:6.10.4:compile
[INFO] com.github.mkolisnyk:cucumber-report-generator:jar:1.3.5:test
[INFO] io.cucumber:cucumber-plugin:jar:6.10.4:compile
[INFO] io.cucumber:cucumber-core:jar:6.10.4:compile
[INFO] io.cucumber:datatable:jar:3.5.0:compile
[INFO] io.cucumber:cucumber-gherkin:jar:6.10.4:compile
[INFO] io.cucumber:cucumber-gherkin-messages:jar:6.10.4:compile
[INFO] io.cucumber:cucumber-testng:jar:6.10.4:compile
[INFO] info.cukes:cucumber-jvm-deps:jar:1.0.5:test
[INFO] io.cucumber:cucumber-junit:jar:6.10.4:compile
[INFO] info.cukes:cucumber-java:jar:1.2.5:test
[INFO] net.masterthought:cucumber-reporting:jar:3.8.0:compile
[INFO] io.cucumber:cucumber-java8:jar:6.10.4:compile
[INFO] io.cucumber:messages:jar:15.0.0:compile
[INFO] io.cucumber:tag-expressions:jar:3.0.1:compile
[INFO] io.cucumber:create-meta:jar:4.0.0:compile
[INFO] info.cukes:cucumber-html:jar:0.2.3:test
[INFO] io.cucumber:cucumber-java:jar:6.10.4:compile
[INFO] io.cucumber:cucumber-expressions:jar:10.3.0:compile
[INFO] info.cukes:cucumber-junit:jar:1.2.5:test
[INFO] info.cukes:cucumber-testng:jar:1.2.5:test
[INFO] info.cukes:cucumber-core:jar:1.2.5:test
[INFO] io.cucumber:cucumber-jvm-deps:jar:1.0.6:provided
The correct syntax for Scenario Outline is:
When I add "<animal>" to the search box
#When("^I add \"([^\"]*)\" to the search box$")
// Or with Cucumber Expressions:
#When("I add {string} to the search box")
The important part is that the < and > are only present in the scenario file, not in the step definition. Consider that <animal> will be replaced (as in a string replacement) automatically by each value of the examples provided.
Note: you have the same mistake in the Then.
I have setup multiple jobs in Jenkins, each running a set of scenarios with a particular set of tags.
I am running them using top-level Maven target with the following Goals and parameters:
clean test -Dcucumber.options="--tags #RunThis"
This was running fine two weeks ago, but today when I reran the job no scenarios were getting executed.
Below is the code in FeatureRunner.java
#RunWith(Cucumber.class)
#CcucumberOptions(
monochrome = true,
dryRun = false,
junit = {"--allow-started-ignored"},
plugin = {"pretty"},
features = "src/test/java/test/features/",
tags = "#RunThis",
glue = {"test/testUtils", "test/steps", "src/test/java/test/steps", "resources", "testUtils"}
)
public class FeatureRunner {
}
I have named scenarios in the below format:
#RunThis
Scenario Outline: <identifier> - <testcaseName>
When ...
And ...
Then ...
Examples:
| identifier | testcaseName | ...
| Test ID 1 | Sample test case name | ...
I'm getting the below message in build logs:
---------------------------------------------------
T E S T S
---------------------------------------------------
Results :
Tests run: 0, Failures: 0, Errors: 0, Skipped: 0
[INFO] ---------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ---------------------------------------------------------------
How do I fix this?
I'm working on a project which uses a combination of Windows, Java, Groovy, Gradle and Cucumber. This combination gives me some problems on my Windows machine that my *NIX colleagues are not experiencing. Upon running the gradle build, gradle wants to output some reports. The location and filename of these reports is apparently determined by the definition or output of the Cucumber tests. The name used is unfortunately not something that can be used as a filename, so I'm getting an IOException for each test report.
For the Cucumber test, we use the following structure:
Scenario Outline: Receive and parse ReturnItem from Service
Given The message from service return item outlined in <messagePath>
When We process the message
Then XXX posted a message to YYY on topic <topic> with event <eventType>
And payload matches <resultPath>
| messagePath | topic | eventType | resultPath |
| /test/testxml.xml | test_topic | EVENT_TYPE | /result/result.json |
After running this, I receive the following exception:
Caused by: org.gradle.api.UncheckedIOException: Could not write to file 'C:\xxx\project\build\reports\tests\test\packages\| \test\testxml.xml | test_topic | EVENT_TYPE | \result\result.html'.
at org.gradle.internal.IoActions$TextFileWriterIoAction.execute(IoActions.java:151)
at org.gradle.internal.IoActions$TextFileWriterIoAction.execute(IoActions.java:127)
at org.gradle.internal.IoActions.writeTextFile(IoActions.java:45)
at org.gradle.reporting.HtmlReportRenderer$DefaultHtmlReportContext.renderHtmlPage(HtmlReportRenderer.java:118)
at org.gradle.api.internal.tasks.testing.report.DefaultTestReport$HtmlReportFileGenerator.run(DefaultTestReport.java:147)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:300)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:292)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:174)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.access$900(DefaultBuildOperationExecutor.java:48)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$ParentPreservingQueueWorker.execute(DefaultBuildOperationExecutor.java:342)
at org.gradle.internal.operations.DefaultBuildOperationQueue$WorkerRunnable.runOperation(DefaultBuildOperationQueue.java:230)
at org.gradle.internal.operations.DefaultBuildOperationQueue$WorkerRunnable.access$600(DefaultBuildOperationQueue.java:172)
at org.gradle.internal.operations.DefaultBuildOperationQueue$WorkerRunnable$1.call(DefaultBuildOperationQueue.java:209)
at org.gradle.internal.operations.DefaultBuildOperationQueue$WorkerRunnable$1.call(DefaultBuildOperationQueue.java:203)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:154)
at org.gradle.internal.operations.DefaultBuildOperationQueue$WorkerRunnable.runBatch(DefaultBuildOperationQueue.java:203)
at org.gradle.internal.operations.DefaultBuildOperationQueue$WorkerRunnable.run(DefaultBuildOperationQueue.java:177)
... 3 more
Caused by: java.io.IOException: Unable to create directory 'C:\xxx\project\project-test\build\reports\tests\test\packages\| \test\testxml.xml | test_topic | EVENT_TYPE | \result'
at org.gradle.internal.IoActions$TextFileWriterIoAction.execute(IoActions.java:141)
... 19 more
Does anybody know how to fix this? The only 'solution' I could come up with is disabling the reports, which works, but is more a workaround than a solution. For disabling I used the following configuration in the gradle.build for this:
apply plugin: 'java'
apply plugin: 'groovy'
test {
reports {
junitXml.enabled = false
html.enabled = false
}
}
(Inspired by: How to make Gradle build produce HTML test report instead of XML default?)
I finally found the culprit. Apparently these filenames correspond to the default behaviour of JUnit for report generation of Cucumber tests. On *NIX, this doesn't provide any problem. On Windows however, this will result in an exception due to the pipes in the Examples. The IOException is somewhat special apparently, since the most exceptions that I found on the internet were FileNotFoundExceptions. That explains why it took me so long to find an answer, I focused on the exception.
The solution here is to use the following JUnitOption as an #CucumberOptions annotation when running the Cucumber tests: --filename-compatible-names.
A code example for Java & Spring looks like this:
#RunWith(Cucumber.class)
#CucumberOptions(junit = {"--filename-compatible-names"})
public class CucumberRunner {
}
It would be nice if these kind of non-breaking OS dependent options would be default instead of optional.
Based upon the information provided, it looks like it's trying to create a directory called:
'C:\xxx\project\project-test\build\reports\tests\test\packages\| \test\testxml.xml | test_topic | EVENT_TYPE | \result'
Can you show the code around passing in messagePath? I suspect you are passing in the entire row of data rather than just the messagePath (I'm going to take a wild guess that you are performing a .toString() on an array instead of passing in the first element of the array)
I'm trying use karate for e2e tests and have started with a minimal setup. I want to create some config items in karate-config.js for use in the tests but karate is reporting that file is not a js function and hence the test fails trying to get the config:
Warning: Nashorn engine is planned to be removed from a future JDK release
12:16:35.264 [Test worker] WARN com.intuit.karate - not a js function or feature file: read('classpath:karate-config.js') - [type: NULL, value: null]
---------------------------------------------------------
feature: classpath:karate/insurer.feature
scenarios: 1 | passed: 0 | failed: 1 | time: 0.0163
---------------------------------------------------------
HTML report: (paste into browser to view) | Karate version: 0.9.1
file:/Users/srowatt/dev/repos/api/price-service/build/surefire-reports/karate.insurer.html
---------------------------------------------------------
-unknown-:4 - javascript evaluation failed: priceBaseUrl, ReferenceError: "priceBaseUrl" is not defined in <eval> at line number 1
org.opentest4j.AssertionFailedError: -unknown-:4 - javascript evaluation failed: priceBaseUrl, ReferenceError: "priceBaseUrl" is not defined in <eval> at line number 1
This is my karate-config.js:
function fn() {
return {
priceBaseUrl: "http://localhost:8080"
};
}
This is my insurer.feature test:
Feature: which creates insurers
Background:
* url priceBaseUrl
* configure logPrettyRequest = true
* configure logPrettyResponse = true
Scenario: basic roundtrip
# create a new insurer
Given path 'insurers'
And request { name: 'Sammy Insurance', companyCode: '99' }
When method post
Then status 201
And match response == { resourceId: '#number', version: 0, createdBy: 'anonymousUser' }
* def insurerId = response.resourceId
# get insurer by resource id
Given path 'insurers', insurerId
When method get
Then status 200
And match response == { id: '#(id)', name: 'Sammy Insurance', companyCode: '99' }
This is the InsurerTest.java test runner:
package karate;
import com.intuit.karate.junit5.Karate;
class InsurerTest {
#Karate.Test
public Karate testInsurer() {
return new Karate().feature("classpath:karate/insurer.feature");
}
}
Please use below code in the karate-config.js
function() {
return priceBaseUrl='http://localhost:8080';
}
When I see this:
Warning: Nashorn engine is planned to be removed from a future JDK release
I suspect you are on Java 9 or 11 ? To be honest, we haven't fully tested Karate on those versions of Java yet. Would it be possible for you to confirm that Java 8 (maybe 9 / 10 also) is OK.
That said, we are interested in resolving this as soon as possible, so if you can submit a sample project where we can replicate this, please do so: https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue
EDIT: Karate 1.0 will use GraalVM instead of Nashorn and will run on even JDK 16: https://software-that-matters.com/2021/01/27/7-new-features-in-karate-test-automation-version-1_0/