In Step 3, we created the Lambda function that will provide the functionality of the Alexa Skill we defined in Step 1, we wired everything up and then we tested our Skill. So far so good. However, that’s an awful long way round to test the Skill Request and Response. It would be nice if we could set up a unit test project and unit test our Lambda function without having to deploy it.
It turns out, we can.
When we created the Lambda function project in Step 3, we selected the AWS Lambda Project with Tests template. So we already have a Tests project and a stubbed out xunit test. (Note: Because we are using the .Net Core for our Lambda function, the normal Microsoft Unit Testing Framework doesn’t work (because it uses the full .Net platform) and so the AWS template uses xunit.)
The tricky part of Unit Testing our Lambda function is that we need to test them FunctionHandler method, which takes a SkillRequest and a Context as parameters:
public SkillResponse FunctionHandler(SkillRequest input, ILambdaContext ctx)
In order to Unit Test our simple GetTodaysDateIntent, we will need to set up a SkillRequest that names that Intent. Like so:
using AlexaAPI; using AlexaAPI.Request; using AlexaAPI.Response; using Amazon.Lambda.TestUtilities; using System.Collections.Generic; using Xunit;
var intent = new Intent(); intent.Name = "GetTodaysDateIntent"; intent.ConfirmationStatus = "NONE"; var request = new Request(); request.Intent = intent; request.Locale = "en-US"; request.Type = AlexaConstants.IntentRequest; var interfaces = new Dictionary<string, object>(); var device = new Device(); device.SupportedInterfaces = interfaces; var sysObj = new SystemObject(); sysObj.Device = device; var skillContext = new Context(); skillContext.System = sysObj; var session = new Session(); var skillRequest = new SkillRequest(); skillRequest.Request = request; skillRequest.Context = skillContext; skillRequest.Session = session;
With that code to create the skillRequest, this line will create the Lambda Context:
var context = new TestLambdaContext();
Now we can create the Function instance:
var function = new MyAlexaSkill.Lambda.Function();
And then we can call the FunctionHandler method to test the Intent:
var result = function.FunctionHandler(skillRequest, context);
A few Assertions will make sure we got the response we are looking for:
Assert.NotNull(result); Assert.NotNull(result.Response); Assert.NotNull(result.Response.OutputSpeech); Assert.Equal("<speak>Today's date is 5/15/2018 12:00:00 AM</speak>", (result.Response.OutputSpeech as SsmlOutputSpeech).Ssml);
Putting it all together, we get this Unit Test:
[Fact] public void TestGetTodaysDateIntent() { var intent = new Intent(); intent.Name = "GetTodaysDateIntent"; intent.ConfirmationStatus = "NONE"; var request = new Request(); request.Intent = intent; request.Locale = "en-US"; request.Type = AlexaConstants.IntentRequest; var interfaces = new Dictionary<string, object>(); var device = new Device(); device.SupportedInterfaces = interfaces; var sysObj = new SystemObject(); sysObj.Device = device; var skillContext = new Context(); skillContext.System = sysObj; var session = new Session(); var skillRequest = new SkillRequest(); skillRequest.Request = request; skillRequest.Context = skillContext; skillRequest.Session = session; var context = new TestLambdaContext(); var function = new MyAlexaSkill.Lambda.Function(); var result = function.FunctionHandler(skillRequest, context); Assert.NotNull(result); Assert.NotNull(result.Response); Assert.NotNull(result.Response.OutputSpeech); Assert.Equal("<speak>Today's date is 5/15/2018 12:00:00 AM</speak>", (result.Response.OutputSpeech as SsmlOutputSpeech).Ssml); }
And there you have it, a Unit Test to test a simple Alexa Skill Intent.
[…] out Step 3a to see how to Unit Test your Alexa Skill Intent without publishing anything to […]
This doesn’t seem to work for me, lots of little errors. Has this changed a lot since May?
What’s not working? Maybe I need to update the docs. Alexa and AWS are evolving rapidly, so it’s possible there are breaking changes. Thanks.