tech.guitarrapc.cóm

Technical updates

.NET Core on Lambda で テスト、ローカル実行、async/await、ロギングについて

さて、AWS Lambda の続きです。

tech.guitarrapc.com

Lambda というか サーバーレスに限らず、ローカル実行ができるか、言語機能の対応状況、ログ確認方法は開発の基本となります。NuGetパッケージの対応状況や他を見る前にざっと確認しておきましょう。

目次

テスト

新規プロジェクトとしてSimpleAsyncFunctionという名前で、AWS Lambda Project with Tests (.NET Core)で作成します。

with Tests を選ぶことで、xUnit によるテストプロジェクトが追加されます。あくまでもローカル実行ではなく、テストプロジェクトの追加であるということに気を付けてください。

前回同様、dotnet restore をして新規プロジェクトのパッケージを復元したら、Test Explorer でテストを実行してみましょう。Empty Project なので、全部大文字になることを期待していますので、適当に絶対に通らないテストも追加してみて失敗することを確認します。

gist.github.com

通らなかったところを、Assert.NotEqual("hogemoge", upperCase); にすれば当然通りますね。*1

いたって普通の xUnit テストと分かります。TestLambdaContextAmazon.Lambda.TestUtilities 名前空間に存在しますが、いい感じで扱えそうですね。

ローカル実行

Node.js においてローカルでイベント送信を検証するときには、_testdriver.js を作っていましたね。*2

aws.typepad.com

.NET Core 版のLambda は、単純なコンソールアプリです。そこで、project.json で buildOptionsemitEntryPointtrue にした上で、エントリポイントとして、ProgramクラスのMainスタティックメソッドを用意してあげればok です。

gist.github.com

Lambda内部の関数はローカル変数の状態が見えない

Program 内はローカル変数もバッチリです。が、Lambda 本体の関数においてはブレークポイントは貼れるもののローカル変数が見えません。Watch Window で変数を見ようとすると error CS0012: The type 'ILambdaContext' is defined in an assembly that is not referenced. You must add a reference to assembly 'Amazon.Lambda.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=885c28607f98e604'. となっています。

project.json でも Amazon.Lambda.Core は参照しているのですが、何じゃろほい...。

async/await しているときの注意

AWS Lambda は、async/await な関数でも呼べます。いいですね。とても嬉しいです。Logger を組まない限りは落ちることなくローカル実行できています。

gist.github.com

ただ、後述のロガーを仕込んでおいてローカル実行で .Result で待ち受けると nullぽります。

System.NullReferenceException: Object reference not set to an instance of an object.

これはProgram.cs の ローカル実行時に null ではなく LambdaContext を渡せばokです。具体的には次の記事に書きました。

tech.guitarrapc.com

async/await

サンプルがドキュメントにあります。

時間がかかる処理があるという前提で、Task.Delay を組んだメソッドを非同期に実行させるなら次のようになります。

gist.github.com

普通ですね。何も違和感なくつかえます。

ロギング

ロギングがどれだけスムーズかは開発効率に重大な影響を及ぼします。今回は最もシンプルで既定で設定されている CloudWatch Logs へのログ出力を見てみます。

C# からのログ出力は、3つあるとドキュメントにあります。

gist.github.com

確認してみると次の動作になります。

ロガー Lambdaコンソールでの出力 CloudWatch Logs への出力 Line出力の可否
Console.Write X O X
Console.WirteLine X O O
LambdaLogger.Log O O X
ILambdaContext.Logger.LogLine O O O
ILambdaContext.Logger.Log O O X

結果、私は ILambdaContext.Logger.LogLine を使うことが多いです。AzureFunctions と似てますね。

まとめ

テスト、ローカルデバッグ、async/await、ロギングと気になるポイントを見てみました。

なかなか素直な作りなので、安心ですね。.csx と違ってローカル実行に制限がほぼないのが素晴らしいです。

今回のサンプルもリポジトリに追加しておきました。

github.com

*1:意味はありませんがただの試しです

*2:_testdriver.jsではus-west-2リージョンがデフォルト は注意ですね