Unit Testing an Alexa Skill in C# – Step 3a

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.

 

 

 

 

 

 

 

Setting up Eclipse for Testing

So I started trying to figure out how to do Unit testing in Eclipse.
Eclipse defaults to JUnit 3 tests, but I want to use JUnit 4 tests. But the Eclipse JUnit 4 plugin is version 4.3 and I want to use 4.4. Then there is the difference between Assert.True and Assert.That, the latter requiring (or at least benefiting from) Hamcrest.
So I finally removed the Eclipse Junit 4.3 library from my BuildPath and added the junit-4.4.jar and hamcrest-all-1.1.jar instead.
In the process, I came across this Unit Testing in Eclipse page, which includes the fit.jar. Well, that launched me into another search as I tried to figure out how to run Fit tests in Eclipse. It turns out that Chengyao Deng wrote his masters thesis on this topic. That led me to the FitClipse Installation Instructions.
Well, my testing configuration wouldn’t be complete without jMock, so I found the jmocklipse site. No code present, just a good idea in Google’s suite of good ideas. Oh well, I can include the external jar manually.
So, now I have Junit, Hamcrest, Fit and jMock all set up and ready to test.
Now…if only I had something to test…

Further Reading:
FIT and Eclipse
Using JUnit with Eclipse IDE