

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 以 C\# 測試 AWS Lambda 函數
<a name="dotnet-csharp-testing"></a>

**注意**  
如需測試無伺服器解決方案之技術和最佳實務的完整介紹，請參閱[測試函數](testing-guide.md)章節。

 測試無伺服器函數會使用傳統的測試類型和技術，但您也必須考慮測試整個無伺服器應用程式。以雲端為基礎的測試會為您的函數和無伺服器應用程式提供**最準確的**品質測量標準。

 無伺服器應用程式架構包括透過 API 呼叫提供關鍵應用程式功能的受管服務。因此，您的開發週期應包括自動化測試，以便在函數和服務互動時驗證功能。

 如果您未建立以雲端為基礎的測試，則可能會因本機環境與部署環境之間的差異而遇到問題。您的持續整合程序應先針對雲端佈建的一組資源進行測試，然後再將程式碼升級至下一個部署環境 (例如 QA、暫存或生產環境)。

 繼續閱讀這份簡短指南，了解無伺服器應用程式的測試策略，或造訪[無伺服器測試範例儲存庫](https://github.com/aws-samples/serverless-test-samples)，深入了解所選語言和執行期的特定實際範例。

 ![illustration showing the relationship between types of tests](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/test-type-illustration2.png) 

 若為無伺服器測試，您仍需要寫入*單元*、*整合*及*端對端*測試。
+ **單元測試**：針對一組隔離的程式碼區塊進行的測試。例如，驗證商業邏輯以計算指定的特定項目與目的地的運費。
+ **整合測試**：涉及到兩個以上元件或服務進行互動的測試 (通常在雲端環境)。例如，驗證函數是否有處理佇列中的事件。
+ **端對端測試**：驗證整個應用程式行為的測試。例如，確保基礎設施的設定正確無誤，以及事件如預期在服務之間流動，以記錄客戶的訂單。

## 測試無伺服器應用程式
<a name="dotnet-csharp-testing-techniques-for-serverless-applications"></a>

 通常會混合使用多種方法來測試無伺服器應用程式程式碼，包括在雲端進行測試、透過模擬物件進行測試，以及偶爾使用模擬器進行測試。

### 在雲端進行測試
<a name="dotnet-csharp-testing-in-the-cloud"></a>

 在雲端進行測試對所有測試階段 (包括單元測試、整合測試和端對端測試) 來說都很有價值。您可以針對部署在雲端中的程式碼執行測試，並與雲端服務互動。這是**最準確**的程式碼品質測量方法。

 您可以透過主控台使用測試事件，輕鬆在雲端對 Lambda 函數進行偵錯。一個*測試事件*是函數的 JSON 輸入。如果您的函數不需要輸入，該事件可以是空白的 JSON 文件 `({})`。主控台提供各種服務整合的範例事件。在主控台中建立事件後，您可以與團隊分享事件，讓測試變得更容易，結果更一致。

**注意**  
在[控制台中測試函數](testing-functions.md)是簡便快速的入門方式，而將測試週期自動化可確保應用程式的品質和開發速度。

### 測試工具
<a name="dotnet-csharp-testing-tools"></a>

為了加速開發週期，您可以在測試函數時使用多種工具和技巧。例如，[AWS SAM Accelerate](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli-sync.html) 和 [AWS CDK 監看模式](https://docs.aws.amazon.com/cdk/v2/guide/cli.html#cli-deploy-watch)都可以縮短更新雲端環境所需的時間。

您定義 Lambda 函數程式碼的方式，讓您可輕鬆加入單元測試。Lambda 需要使用公有無參數建構函數來初始化類別。引入第二個內部建構函數，可讓您控制應用程式使用的相依項。

```
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace GetProductHandler;

public class Function
{
    private readonly IDatabaseRepository _repo;
    
    public Function(): this(null)
    {
    }
    
    internal Function(IDatabaseRepository repo)
    {
        this._repo = repo ?? new DatabaseRepository();
    }
    
    public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest request)
    {
        var id = request.PathParameters["id"];
        
        var databaseRecord = await this._repo.GetById(id);
        
        return new APIGatewayProxyResponse 
        {
            StatusCode = (int)HttpStatusCode.OK,
            Body = JsonSerializer.Serialize(databaseRecord)
        };
    }
}
```

若要為此函數編寫測試，您可以初始化 `Function` 類別的新執行個體，並傳入 `IDatabaseRepository` 的模擬實作。以下範例使用 `XUnit`、`Moq` 和 `FluentAssertions` 來編寫簡單的測試，確保 `FunctionHandler` 會傳回 200 狀態碼。

```
using Xunit;
using Moq;
using FluentAssertions;

public class FunctionTests
{
    [Fact]
    public async Task TestLambdaHandler_WhenInputIsValid_ShouldReturn200StatusCode()
    {
        // Arrange
        var mockDatabaseRepository = new Mock<IDatabaseRepository>();
        
        var functionUnderTest = new Function(mockDatabaseRepository.Object);
        
        // Act
        var response = await functionUnderTest.FunctionHandler(new APIGatewayProxyRequest());
        
        // Assert
        response.StatusCode.Should().Be(200);
    }
}
```

如需更詳細的範例，包括非同步測試範例在內，請參閱 GitHub 上的 [.NET 測試範例儲存庫](https://github.com/aws-samples/serverless-test-samples/tree/main/dotnet-test-samples)。