Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #139 from martincostello/Test-Lambda-Server
Add Lambda test server for integration tests
- Loading branch information
Showing
12 changed files
with
1,196 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
// Copyright (c) Martin Costello, 2017. All rights reserved. | ||
// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information. | ||
|
||
using System.Runtime.CompilerServices; | ||
|
||
[assembly: InternalsVisibleTo("LondonTravel.Skill.Tests")] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// Copyright (c) Martin Costello, 2017. All rights reserved. | ||
// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information. | ||
|
||
using System; | ||
using System.Threading; | ||
using System.Threading.Channels; | ||
using System.Threading.Tasks; | ||
using Alexa.NET.Request; | ||
using Alexa.NET.Request.Type; | ||
using Alexa.NET.Response; | ||
using MartinCostello.LondonTravel.Skill.Integration; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.Logging; | ||
using Newtonsoft.Json; | ||
using Shouldly; | ||
using Xunit; | ||
using Xunit.Abstractions; | ||
|
||
namespace MartinCostello.LondonTravel.Skill | ||
{ | ||
public class EndToEndTests : FunctionTests | ||
{ | ||
public EndToEndTests(ITestOutputHelper outputHelper) | ||
: base(outputHelper) | ||
{ | ||
} | ||
|
||
[Fact] | ||
public async Task Alexa_Function_Can_Process_Request() | ||
{ | ||
// Arrange | ||
SkillRequest request = CreateRequest<LaunchRequest>(); | ||
request.Request.Type = "LaunchRequest"; | ||
|
||
string json = JsonConvert.SerializeObject(request); | ||
|
||
void Configure(IServiceCollection services) | ||
{ | ||
services.AddLogging((builder) => builder.AddXUnit(this)); | ||
} | ||
|
||
using var server = new LambdaTestServer(Configure); | ||
using var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(2)); | ||
|
||
await server.StartAsync(cancellationTokenSource.Token); | ||
|
||
ChannelReader<LambdaResponse> reader = await server.EnqueueAsync(json); | ||
|
||
// Queue a task to stop the Lambda function as soon as the response is processed | ||
_ = Task.Run(async () => | ||
{ | ||
await reader.WaitToReadAsync(cancellationTokenSource.Token); | ||
if (!cancellationTokenSource.IsCancellationRequested) | ||
{ | ||
cancellationTokenSource.Cancel(); | ||
} | ||
}); | ||
|
||
using var httpClient = server.CreateClient(); | ||
|
||
// Act | ||
await Function.RunAsync(httpClient, cancellationTokenSource.Token); | ||
|
||
// Assert | ||
reader.TryRead(out LambdaResponse result).ShouldBeTrue(); | ||
|
||
result.ShouldNotBeNull(); | ||
result.IsSuccessful.ShouldBeTrue(); | ||
result.Content.ShouldNotBeNull(); | ||
result.Content.ShouldNotBeEmpty(); | ||
|
||
json = System.Text.Encoding.UTF8.GetString(result.Content); | ||
var actual = JsonConvert.DeserializeObject<SkillResponse>(json); | ||
|
||
actual.ShouldNotBeNull(); | ||
|
||
ResponseBody response = AssertResponse(actual, shouldEndSession: false); | ||
|
||
response.Card.ShouldBeNull(); | ||
response.Reprompt.ShouldBeNull(); | ||
|
||
response.OutputSpeech.ShouldNotBeNull(); | ||
response.OutputSpeech.Type.ShouldBe("SSML"); | ||
|
||
var ssml = response.OutputSpeech.ShouldBeOfType<SsmlOutputSpeech>(); | ||
ssml.Ssml.ShouldBe("<speak>Welcome to London Travel. You can ask me about disruption or for the status of any tube line, London Overground, the D.L.R. or T.F.L. Rail.</speak>"); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
49 changes: 49 additions & 0 deletions
49
test/LondonTravel.Skill.Tests/Integration/LambdaRequest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// Copyright (c) Martin Costello, 2017. All rights reserved. | ||
// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information. | ||
|
||
using System; | ||
|
||
namespace MartinCostello.LondonTravel.Skill.Integration | ||
{ | ||
/// <summary> | ||
/// A class representing a request to an AWS Lambda function. | ||
/// </summary> | ||
public class LambdaRequest | ||
{ | ||
/// <summary> | ||
/// Initializes a new instance of the <see cref="LambdaRequest"/> class. | ||
/// </summary> | ||
/// <param name="content">The raw content of the request to invoke the Lambda function with.</param> | ||
/// <param name="awsRequestId">The optional AWS request Id to invoke the Lambda function with.</param> | ||
/// <exception cref="ArgumentNullException"> | ||
/// <paramref name="content"/> is <see langword="null"/>. | ||
/// </exception> | ||
public LambdaRequest(byte[] content, string awsRequestId = null) | ||
{ | ||
Content = content ?? throw new ArgumentNullException(nameof(content)); | ||
AwsRequestId = awsRequestId ?? Guid.NewGuid().ToString(); | ||
} | ||
|
||
/// <summary> | ||
/// Gets the AWS request Id for the request to the function. | ||
/// </summary> | ||
public string AwsRequestId { get; } | ||
|
||
/// <summary> | ||
/// Gets the raw byte content of the request to the function. | ||
/// </summary> | ||
public byte[] Content { get; } | ||
|
||
/// <summary> | ||
/// Gets or sets an optional string containing the serialized JSON | ||
/// for the client context when invoked through the AWS Mobile SDK. | ||
/// </summary> | ||
public string ClientContext { get; set; } | ||
|
||
/// <summary> | ||
/// Gets or sets an optional string containing the serialized JSON for the | ||
/// Amazon Cognito identity provider when invoked through the AWS Mobile SDK. | ||
/// </summary> | ||
public string CognitoIdentity { get; set; } | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
test/LondonTravel.Skill.Tests/Integration/LambdaResponse.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// Copyright (c) Martin Costello, 2017. All rights reserved. | ||
// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information. | ||
|
||
namespace MartinCostello.LondonTravel.Skill.Integration | ||
{ | ||
/// <summary> | ||
/// A class representing a response from an AWS Lambda function. This class cannot be inherited. | ||
/// </summary> | ||
public sealed class LambdaResponse | ||
{ | ||
/// <summary> | ||
/// Initializes a new instance of the <see cref="LambdaResponse"/> class. | ||
/// </summary> | ||
/// <param name="content">The raw content of the response from the Lambda function.</param> | ||
/// <param name="isSuccessful">Whether the response indicates the request was successfully handled.</param> | ||
internal LambdaResponse(byte[] content, bool isSuccessful) | ||
{ | ||
Content = content; | ||
IsSuccessful = isSuccessful; | ||
} | ||
|
||
/// <summary> | ||
/// Gets the raw byte content of the response from the function. | ||
/// </summary> | ||
public byte[] Content { get; } | ||
|
||
/// <summary> | ||
/// Gets a value indicating whether the response indicates the request was successfully handled. | ||
/// </summary> | ||
public bool IsSuccessful { get; } | ||
} | ||
} |
Oops, something went wrong.