问题
I'm trying to unit test a DialogflowApp
locally by using the firebase shell environment. (in a cli do firebase experimental:functions:shell and then call my methods)
I have followed this guide by google https://firebase.google.com/docs/functions/local-emulator but they don't use the DialogflowApp where the invoked function tries to bind a request object containing intents and parameters like this ->
exports.myFunction = functions.https.onRequest((request, response) => {
const app = new App({ request, response });
function myMethod(app) {
let myArgument = app.getArgument(MY_ARGUMENT);
app.tell('Here we are responding');
}
let actionMap = new Map();
actionMap.set(MYMETHOD_ACTION, myMethod);
app.handleRequest(actionMap);
});
Regardless of what request object I send in the CLI, like this myFunction(require("../test/testdata.json"))
, the request body object is empty, like this body: {}
which means I can't do app.handleRequest()
or app.getArgument()
. The error message I get is
RESPONSE RECEIVED FROM FUNCTION: 400, Action Error: no matching intent handler for: null
I thought that if I populated testdata.json with the json request data shown in Actions on Google -> console.actions.google.com -> Simulator it would be valid data but no.
My question is, how can i mock my request data so that I can start unit testing my fullfillment methods locally?
EDIT 1:
firebase > myMethod.post("/").form(require("../test/testdata.json"))
Sent request to function.
firebase > info: User function triggered, starting execution
info: Function crashed
info: TypeError: Cannot destructure property `parameters` of 'undefined' or 'null'.
if we look in dialogflow_app.js we can see this code for fetching an argument value
getArgument (argName) {
debug('getArgument: argName=%s', argName);
if (!argName) {
error('Invalid argument name');
return null;
}
const { parameters } = this.body_.result;
if (parameters && parameters[argName]) {
return parameters[argName];
}
return this.getArgumentCommon(argName);
}
this.body_ is always just empty {}
, regardless of how and what I send into the method when running locally.
EDIT 3
firebase > myMethod({method: "post",json: true, body: require("../test/testdata.json")})
Sent request to function.
firebase > info: User function triggered, starting execution
info: Function crashed
info: TypeError: Cannot destructure property parameters
of 'undefined' or 'null'.
回答1:
Invoking a Firebase HTTPS function using the shell requires a different form. It takes the parameters that the request module does, so in order to emulate a webhook, it will be something like this:
myfunction({
method: 'POST',
json: true,
body: require("../test/testdata.json")
});
These three parameters are important:
- You need to specify that this is a POST operation
- You need to indicate that the body will be JSON. This will send the correct header and won't try to send the body as x-www-form-urlencoded
- You need to include the body. As an object is ok because you've set the json parameter to true.
来源:https://stackoverflow.com/questions/48791293/unit-test-actions-on-google-dialogflow-locally