{"id":2523,"date":"2024-04-24T08:48:18","date_gmt":"2024-04-24T15:48:18","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/semantic-kernel\/?p=2523"},"modified":"2024-04-24T08:48:18","modified_gmt":"2024-04-24T15:48:18","slug":"unit-testing-with-semantic-kernel","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/agent-framework\/unit-testing-with-semantic-kernel\/","title":{"rendered":"Unit Testing with Semantic Kernel"},"content":{"rendered":"<p>Hi all,<\/p>\n<p><span data-contrast=\"none\">Testing is an integral part of the software development process. Unit testing allows to test your functionality in isolation. This usually means that instead of performing real work (e.g. sending HTTP request to LLM), it needs to be replaced with something that only simulates the work and return some predefined result, which will be used in testing class. As Semantic Kernel developers, we want to make sure that it&#8217;s easy to write unit tests for classes that use main library components &#8211; Kernel, Plugins and Functions.<\/span><\/p>\n<p><span data-contrast=\"none\">This article shows how to test the functionality in .NET applications which use Semantic Kernel. For demonstration purposes, we will use <\/span><code class=\"language-cs language-csharp\">xUnit<\/code><span data-contrast=\"none\"> as test framework and <code class=\"language-cs language-csharp\">Moq<\/code><\/span><span data-contrast=\"none\">\u00a0as mocking library.<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"none\">Let&#8217;s take a common scenario, where there is a service that does some work, and <\/span><span data-contrast=\"none\">Kernel<\/span><span data-contrast=\"none\"> object is a dependency of that service:<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-cs language-csharp\"><code class=\"language-cs language-csharp\">public class MyService(Kernel kernel) \r\n{ \r\n    private readonly Kernel _kernel = kernel; \r\n \r\n    public async Task&lt;FunctionResult&gt; DoWorkAsync(KernelFunction function) \r\n        =&gt; await _kernel.InvokeAsync(function); \r\n \r\n    public async Task&lt;FunctionResult&gt; DoWorkAsync(string pluginName, string functionName) \r\n        =&gt; await _kernel.InvokeAsync(pluginName, functionName); \r\n \r\n    public async Task&lt;FunctionResult&gt; DoWorkAsync(string prompt) \r\n        =&gt; await _kernel.InvokePromptAsync(prompt); \r\n}<\/code><\/pre>\n<p><span data-contrast=\"none\">In real-world applications, such services will probably contain more logic, but for simplicity, our service example will call available <\/span><code class=\"language-cs language-csharp\">Kernel<\/code> <span data-contrast=\"none\">methods and return its result.<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"none\">It&#8217;s always possible to create a wrapper around <code class=\"language-cs language-csharp\">Kernel<\/code> (<\/span><span data-contrast=\"none\">in similar way how \u00a0<\/span><code class=\"language-cs language-csharp\">MyService<\/code> <span data-contrast=\"none\">looks now) and use it for mocking and testing purposes, but this article focuses on testing <code class=\"language-cs language-csharp\">Kernel<\/code> <\/span><span data-contrast=\"none\">and functions directly.<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"none\"><code class=\"language-cs language-csharp\">Kernel<\/code> is a container that holds services and plugins, which means that we don\u2019t want to mock <\/span><span data-contrast=\"none\">Kernel<\/span><span data-contrast=\"none\"> directly. Instead, we want to mock its services and plugins. As presented in <code class=\"language-cs language-csharp\">MyService<\/code><\/span><span data-contrast=\"none\">\u00a0class, <code class=\"language-cs language-csharp\">Kernel<\/code> <\/span><span data-contrast=\"none\">has different ways how to execute a function and we will cover them in more detail. Next examples include:<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<ol>\n<li><span data-contrast=\"none\">Plugins \u2013 mocking calls to plugin functions.<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/li>\n<li><span data-contrast=\"none\">Services \u2013 mocking calls to an LLM.<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/li>\n<li><span data-contrast=\"none\">Streaming \u2013 additional considerations when using streaming with both plugin functions and LLM.<\/span><\/li>\n<\/ol>\n<p aria-level=\"3\"><b><span data-contrast=\"none\">InvokeAsync with KernelFunction<\/span><\/b><span data-ccp-props=\"{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:281,&quot;335559739&quot;:281}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"none\">When we do <\/span><code class=\"language-cs language-csharp\">kernel.InvokeAsync(function)<\/code><span data-contrast=\"none\">, <\/span><code class=\"language-cs language-csharp\">InvokeAsync<\/code><span data-contrast=\"none\"> method performs <\/span><code class=\"language-cs language-csharp\">function.InvokeAsync(...)<\/code><span data-contrast=\"none\">, which means that we are interested in mocking\u00a0 <\/span><span data-contrast=\"none\"><code class=\"language-cs language-csharp\">KernelFunction <\/code>behaviour.<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"none\">At the moment, <code class=\"language-cs language-csharp\">KernelFunction<\/code><\/span><span data-contrast=\"none\"> can be either <code class=\"language-cs language-csharp\">KernelFunctionFromMethod<\/code><\/span><span data-contrast=\"none\">, which is some method in C# code, or <code class=\"language-cs language-csharp\">KernelFunctionFromPrompt<\/code><\/span><span data-contrast=\"none\">, which is constructed using prompt template and which will perform a request to LLM. The difference between these 2 types of <code class=\"language-cs language-csharp\">KernelFunction<\/code> <\/span><span data-contrast=\"none\">defines how they need to be mocked.<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"none\">In case when <\/span><span data-contrast=\"none\">Kernel<\/span><span data-contrast=\"none\"> needs to invoke <code class=\"language-cs language-csharp\">KernelFunctionFromMethod<\/code><\/span><span data-contrast=\"none\">, we can simply define a method in our test that will return desired result. For this purpose, we can use <code class=\"language-cs language-csharp\">KernelFunctionFactory<\/code><\/span><span data-contrast=\"none\">, which is static helper class to create different types of functions. Method <code class=\"language-cs language-csharp\">KernelFunctionFactory.CreateFromMethod<\/code><\/span><span data-contrast=\"none\">\u00a0accepts delegate, so we can define our function with desired result as lambda expression, local function or pass existing function as a parameter. For simplicity, we will use lambda expression.<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"none\">Our first method in <code class=\"language-cs language-csharp\">MyService<\/code><\/span><span data-contrast=\"none\">\u00a0accepts <code class=\"language-cs language-csharp\">KernelFunction<\/code><\/span><span data-contrast=\"none\">, so we will create our test function and pass it to the service, where it will be invoked. Here is how the test will look like:<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-cs language-csharp\"><code class=\"language-cs language-csharp\">[Fact] \r\npublic async void DoWorkWithFunction() \r\n{ \r\n    \/\/ Arrange \r\n    var function = KernelFunctionFactory.CreateFromMethod(() =&gt; \"Function result value\"); \r\n    var kernel = new Kernel(); \r\n \r\n    var service = new MyService(kernel); \r\n \r\n    \/\/ Act \r\n    var result = await service.DoWorkAsync(function); \r\n \r\n    \/\/ Assert \r\n    Assert.Equal(\"Function result value\", result.ToString()); \r\n}<\/code><\/pre>\n<p aria-level=\"3\"><b><span data-contrast=\"none\">InvokeAsync with Function and Plugin names<\/span><\/b><span data-ccp-props=\"{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:281,&quot;335559739&quot;:281}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"none\">Kernel<\/span><span data-contrast=\"none\"> holds a collection of plugins, so anytime we want to change <\/span><span data-contrast=\"none\">Kernel<\/span><span data-contrast=\"none\"> behaviour in our tests, we need to pass it with registered plugins that don&#8217;t perform a real work and contain some mock behaviour instead.<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"none\">Our second method in <code class=\"language-cs language-csharp\">MyService<\/code> <\/span><span data-contrast=\"none\">doesn&#8217;t use <code class=\"language-cs language-csharp\">KernelFunction<\/code><\/span><span data-contrast=\"none\">, it accepts Function and Plugin names. This means, that when we initialize our <\/span><span data-contrast=\"none\">Kernel<\/span><span data-contrast=\"none\">, we need to register some plugin with test behaviour, which will satisfy our test case.<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"none\">To create test plugin, we can use static <code class=\"language-cs language-csharp\">KernelPluginFactory<\/code> <\/span><span data-contrast=\"none\">class, which will help to create our plugin. This class contains methods like <code class=\"language-cs language-csharp\">KernelPluginFactory.CreateFromType&lt;T&gt;<\/code><\/span><span data-contrast=\"none\">\u00a0and <code class=\"language-cs language-csharp\">KernelPluginFactory.CreateFromObject<\/code><\/span><span data-contrast=\"none\">, which are useful when our <code class=\"language-cs language-csharp\">KernelFunction<\/code><\/span><span data-contrast=\"none\"> is defined in separate class. These methods will use reflection to get a metadata about plugin class and create <code class=\"language-cs language-csharp\">KernelPlugin<\/code><\/span><span data-contrast=\"none\">\u00a0instance.<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"none\">For testing scenarios, there is a simpler way how to initialize plugin &#8211;<code class=\"language-cs language-csharp\">KernelPluginFactory.CreateFromFunctions<\/code><\/span><span data-contrast=\"none\">\u00a0method. It accepts plugin name and enumeration of <code class=\"language-cs language-csharp\">KernelFunction<\/code><\/span><span data-contrast=\"none\">\u00a0instances. Based on previous example, we already know how to create a function with mocked behaviour using <code class=\"language-cs language-csharp\">KernelFunctionFactory<\/code><\/span><span data-contrast=\"none\">, which means that we can combine two approaches together, which will result in following test:<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-cs language-csharp\"><code class=\"language-cs language-csharp\">[Fact] \r\npublic async Task DoWorkWithFunctionName() \r\n{ \r\n    \/\/ Arrange \r\n    var function = KernelFunctionFactory.CreateFromMethod(() =&gt; \"Function result value\", \"MyFunction\"); \r\n    var plugin = KernelPluginFactory.CreateFromFunctions(\"MyPlugin\", [function]); \r\n    var plugins = new KernelPluginCollection([plugin]); \r\n \r\n    var kernel = new Kernel(plugins: plugins); \r\n \r\n    var service = new MyService(kernel); \r\n \r\n    \/\/ Act \r\n    var result = await service.DoWorkAsync(\"MyPlugin\", \"MyFunction\"); \r\n \r\n    \/\/ Assert \r\n    Assert.Equal(\"Function result value\", result.ToString()); \r\n} <\/code><\/pre>\n<p><span data-contrast=\"none\">As soon as we create our <code class=\"language-cs language-csharp\">KernelPlugin<\/code><\/span><span data-contrast=\"none\">, we can initialize <\/span><span data-contrast=\"none\">Kernel<\/span><span data-contrast=\"none\"> and pass instance of <code class=\"language-cs language-csharp\">KernelPluginCollection<\/code><\/span><span data-contrast=\"none\">, which will hold our test plugin with mocked behaviour. Then, we inject kernel instance to the service, and it will use test function to return configured result.<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<p aria-level=\"3\"><b><span data-contrast=\"none\">InvokePromptAsync<\/span><\/b><span data-ccp-props=\"{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:281,&quot;335559739&quot;:281}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"none\">In previous examples, we mocked <code class=\"language-cs language-csharp\">KernelFunctionFromMethod<\/code><\/span><span data-contrast=\"none\">\u00a0behaviour, but <\/span><span data-contrast=\"none\">Kernel<\/span><span data-contrast=\"none\"> can also hold <code class=\"language-cs language-csharp\">KernelFunctionFromPrompt<\/code><\/span><span data-contrast=\"none\"> functions. As already described, these functions will perform requests to LLM, which means that most probably <code class=\"language-cs language-csharp\">HttpClient<\/code> <\/span><span data-contrast=\"none\">will be involved and in this case more mocking logic will be required.<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"none\">When we do <code class=\"language-cs language-csharp\">kernel.InvokePromptAsync(...)<\/code><\/span><span data-contrast=\"none\">, we just call an extension method that will create instance of <code class=\"language-cs language-csharp\">KernelFunctionFromPrompt<\/code> <\/span><span data-contrast=\"none\">and immediately invoke it.<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"none\"><code class=\"language-cs language-csharp\">KernelFunctionFromPrompt<\/code><\/span><span data-contrast=\"none\"> during invocation will render prompt using configured prompt template and pass that prompt to service, which will be responsible to send a request to LLM. <code class=\"language-cs language-csharp\">KernelFunctionFromPrompt<\/code><\/span><span data-contrast=\"none\"> will try to find an instance of <code class=\"language-cs language-csharp\">IChatCompletionService<\/code><\/span><span data-contrast=\"none\"> or <code class=\"language-cs language-csharp\">ITextGenerationService<\/code><\/span><span data-contrast=\"none\"> service to perform the request. Which means that we can mock <code class=\"language-cs language-csharp\">IChatCompletionService<\/code> <\/span><span data-contrast=\"none\">and return desired result. We also need to register <code class=\"language-cs language-csharp\">IChatCompletionService<\/code><\/span><span data-contrast=\"none\">\u00a0in <\/span><span data-contrast=\"none\">Kernel<\/span><span data-contrast=\"none\">, because that&#8217;s the place where our function will look for it.<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"none\">To define test behaviour of <code class=\"language-cs language-csharp\">IChatCompletionService<\/code><\/span><span data-contrast=\"none\">, it&#8217;s possible to implement that interface with fake class, but easier way would be to use mocking library of your choice. As soon as we have mocked behaviour in place, we need to register it in <\/span><span data-contrast=\"none\">Kernel<\/span><span data-contrast=\"none\"> and invoke our prompt function. Here is an example how the test could look like:<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-cs language-csharp\"><code class=\"language-cs language-csharp\">[Fact] \r\npublic async Task DoWorkWithPrompt() \r\n{ \r\n    \/\/ Arrange \r\n    var mockChatCompletion = new Mock&lt;IChatCompletionService&gt;(); \r\n    mockChatCompletion \r\n        .Setup(x =&gt; x.GetChatMessageContentsAsync( \r\n            It.IsAny&lt;ChatHistory&gt;(), \r\n            It.IsAny&lt;PromptExecutionSettings&gt;(), \r\n            It.IsAny&lt;Kernel&gt;(), \r\n            It.IsAny&lt;CancellationToken&gt;())) \r\n        .ReturnsAsync([new ChatMessageContent(AuthorRole.Assistant, \"AI response\")]); \r\n \r\n    var kernelBuilder = Kernel.CreateBuilder(); \r\n    kernelBuilder.Services.AddSingleton(mockChatCompletion.Object); \r\n \r\n    var kernel = kernelBuilder.Build(); \r\n    var service = new MyService(kernel); \r\n \r\n    \/\/ Act \r\n    var result = await service.DoWorkAsync(\"Prompt to AI\"); \r\n \r\n    \/\/ Assert \r\n    Assert.Equal(\"AI response\", result.ToString()); \r\n} <\/code><\/pre>\n<p><span data-contrast=\"none\">As alternative, if AI connector accepts <code class=\"language-cs language-csharp\">HttpClient<\/code> <\/span><span data-contrast=\"none\">as parameter, it&#8217;s also possible to define test behaviour and mock <code class=\"language-cs language-csharp\">HttpClient<\/code><\/span><span data-contrast=\"none\">.<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<p aria-level=\"3\"><b><span data-contrast=\"none\">Testing streaming scenarios<\/span><\/b><span data-ccp-props=\"{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:281,&quot;335559739&quot;:281}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"none\">In case of streaming, the tests will look very similar to previous examples, with small differences in places where we define our test response and mock <code class=\"language-cs language-csharp\">IChatCompletionService<\/code><\/span><span data-contrast=\"none\">.<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"none\">Let&#8217;s rewrite <code class=\"language-cs language-csharp\">MyService<\/code><\/span><span data-contrast=\"none\">\u00a0to call <\/span><span data-contrast=\"none\">Kernel<\/span><span data-contrast=\"none\"> streaming methods:<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-cs language-csharp\"><code class=\"language-cs language-csharp\">public class MyService(Kernel kernel) \r\n{ \r\n    private readonly Kernel _kernel = kernel; \r\n \r\n    public IAsyncEnumerable&lt;T&gt; DoWorkStreaming&lt;T&gt;(KernelFunction function) \r\n        =&gt; _kernel.InvokeStreamingAsync&lt;T&gt;(function); \r\n \r\n    public IAsyncEnumerable&lt;T&gt; DoWorkStreaming&lt;T&gt;(string pluginName, string functionName) \r\n        =&gt; _kernel.InvokeStreamingAsync&lt;T&gt;(pluginName, functionName); \r\n \r\n    public IAsyncEnumerable&lt;T&gt; DoWorkStreaming&lt;T&gt;(string prompt) \r\n        =&gt; _kernel.InvokePromptStreamingAsync&lt;T&gt;(prompt); \r\n} <\/code><\/pre>\n<p><span class=\"TextRun SCXW264638242 BCX8\" lang=\"EN-GB\" xml:lang=\"EN-GB\" data-contrast=\"none\"><span class=\"NormalTextRun SCXW264638242 BCX8\">Based on this service, the tests will look like following:<\/span><\/span><span class=\"EOP SCXW264638242 BCX8\" data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<pre class=\"prettyprint language-cs language-csharp\"><code class=\"language-cs language-csharp\">[Fact] \r\npublic async Task DoWorkStreamingWithFunction() \r\n{ \r\n    \/\/ Arrange \r\n    async IAsyncEnumerable&lt;int&gt; TestMethod() \r\n    { \r\n        yield return 1; \r\n        yield return 2; \r\n        yield return 3; \r\n    } \r\n \r\n    var function = KernelFunctionFactory.CreateFromMethod(TestMethod); \r\n \r\n    var kernel = new Kernel(); \r\n \r\n    var service = new MyService(kernel); \r\n \r\n    \/\/ Act \r\n    var result = new List&lt;int&gt;(); \r\n    await foreach (var item in service.DoWorkStreaming&lt;int&gt;(function)) \r\n    { \r\n        result.Add(item); \r\n    } \r\n \r\n    \/\/ Assert \r\n    Assert.Equal([1, 2, 3], result); \r\n} \r\n \r\n[Fact] \r\npublic async Task DoWorkWithFunctionName() \r\n{ \r\n    \/\/ Arrange \r\n    async IAsyncEnumerable&lt;int&gt; TestMethod() \r\n    { \r\n        yield return 1; \r\n        yield return 2; \r\n        yield return 3; \r\n    } \r\n \r\n    var function = KernelFunctionFactory.CreateFromMethod(TestMethod); \r\n    var plugin = KernelPluginFactory.CreateFromFunctions(\"MyPlugin\", [function]); \r\n    var plugins = new KernelPluginCollection([plugin]); \r\n \r\n    var kernel = new Kernel(plugins: plugins); \r\n \r\n    var service = new MyService(kernel); \r\n \r\n    \/\/ Act \r\n    var result = new List&lt;int&gt;(); \r\n    await foreach (var item in service.DoWorkStreaming&lt;int&gt;(function)) \r\n    { \r\n        result.Add(item); \r\n    } \r\n \r\n    \/\/ Assert \r\n    Assert.Equal([1, 2, 3], result); \r\n} \r\n \r\n[Fact] \r\npublic async Task DoWorkWithPrompt() \r\n{ \r\n    \/\/ Arrange \r\n    var mockChatCompletion = new Mock&lt;IChatCompletionService&gt;(); \r\n    mockChatCompletion \r\n        .Setup(x =&gt; x.GetStreamingChatMessageContentsAsync( \r\n            It.IsAny&lt;ChatHistory&gt;(), \r\n            It.IsAny&lt;PromptExecutionSettings&gt;(), \r\n            It.IsAny&lt;Kernel&gt;(), \r\n            It.IsAny&lt;CancellationToken&gt;())) \r\n        .Returns(new List&lt;StreamingChatMessageContent&gt;() { new(AuthorRole.Assistant, \"AI response\") }.ToAsyncEnumerable()); \r\n \r\n    var kernelBuilder = Kernel.CreateBuilder(); \r\n    kernelBuilder.Services.AddSingleton(mockChatCompletion.Object); \r\n \r\n    var kernel = kernelBuilder.Build(); \r\n    var service = new MyService(kernel); \r\n \r\n    \/\/ Act \r\n    var result = new List&lt;string&gt;(); \r\n    await foreach (var item in service.DoWorkStreaming&lt;string&gt;(\"Prompt to AI\")) \r\n    { \r\n        result.Add(item); \r\n    } \r\n \r\n    \/\/ Assert \r\n    Assert.Equal([\"AI response\"], result); \r\n}<\/code><\/pre>\n<p><span data-contrast=\"none\">In case of streaming, we still use <code class=\"language-cs language-csharp\">KernelFunctionFactory<\/code> <\/span><span data-contrast=\"none\">and <code class=\"language-cs language-csharp\">KernelPluginFactory<\/code> <\/span><span data-contrast=\"none\">as helper classes to initialize test plugins and functions.<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"none\">The only difference is the result of mocked functions &#8211; instead of returning value directly, we return <code class=\"language-cs language-csharp\">IAsyncEnumerable&lt;T&gt;<\/code><\/span><span data-contrast=\"none\">. We also mock <code class=\"language-cs language-csharp\">IChatCompletionService<\/code> <\/span><span data-contrast=\"none\">differently &#8211; instead of mocking <code class=\"language-cs language-csharp\">GetChatMessageContentsAsync<\/code> <\/span><span data-contrast=\"none\">method, we mock <code class=\"language-cs language-csharp\">GetStreamingChatMessageContentsAsync<\/code><\/span><span data-contrast=\"none\">. We also use <code class=\"language-cs language-csharp\">ToAsyncEnumerable<\/code><\/span><span data-contrast=\"none\">\u00a0method from <code class=\"language-cs language-csharp\">System.Linq.Async<\/code><\/span><span data-contrast=\"none\">\u00a0package to convert our result list to <code class=\"language-cs language-csharp\">IAsyncEnumerable<\/code> <\/span><span data-contrast=\"none\">in easier way.<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<p aria-level=\"3\"><b><span data-contrast=\"none\">Summary<\/span><\/b><span data-ccp-props=\"{&quot;134245418&quot;:true,&quot;134245529&quot;:true,&quot;335559738&quot;:281,&quot;335559739&quot;:281}\">\u00a0<\/span><\/p>\n<p><span data-contrast=\"none\">Provided examples show how to write unit tests for services which use <\/span><span data-contrast=\"none\">Kernel<\/span><span data-contrast=\"none\"> as a dependency. Although these examples focus on unit testing, similar approaches can be used for integration testing.<\/span><span data-ccp-props=\"{&quot;335559738&quot;:240,&quot;335559739&quot;:240}\">\u00a0<\/span><\/p>\n<p>We\u2019re always interested in hearing from you. If you have feedback, questions or want to discuss further, feel free to reach out to us and the community on the<a href=\"https:\/\/github.com\/microsoft\/semantic-kernel\/discussions\">\u00a0discussion boards<\/a> on GitHub! We would also love your support, if you&#8217;ve enjoyed using Semantic Kernel, give us a star on <a href=\"https:\/\/github.com\/microsoft\/semantic-kernel\">GitHub<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hi all, Testing is an integral part of the software development process. Unit testing allows to test your functionality in isolation. This usually means that instead of performing real work (e.g. sending HTTP request to LLM), it needs to be replaced with something that only simulates the work and return some predefined result, which will [&hellip;]<\/p>\n","protected":false},"author":149071,"featured_media":2365,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[17,1],"tags":[48,9,68],"class_list":["post-2523","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-announcements","category-semantic-kernel","tag-ai","tag-semantic-kernel","tag-unit-testing"],"acf":[],"blog_post_summary":"<p>Hi all, Testing is an integral part of the software development process. Unit testing allows to test your functionality in isolation. This usually means that instead of performing real work (e.g. sending HTTP request to LLM), it needs to be replaced with something that only simulates the work and return some predefined result, which will [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/posts\/2523","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/users\/149071"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/comments?post=2523"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/posts\/2523\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/media\/2365"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/media?parent=2523"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/categories?post=2523"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/agent-framework\/wp-json\/wp\/v2\/tags?post=2523"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}