From 74f06914ded4e2e26d034d9a19d662dbe7031a76 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Thu, 27 Nov 2025 20:51:41 +0100 Subject: [PATCH] Add unit tests for `ReadLine` activity (#7110) (#7112) * Add unit tests for `ReadLine` activity (#7110) - Implemented `ReadLineTests` to verify the behavior of the `ReadLine` activity. - Added scenarios for reading input, stream provider usage, and successful completion. - Refactored `ExecuteAsync` helper to streamline test execution with mock dependencies. * Enhance `ReadLine` activity tests with additional scenarios: validate null handling, default provider usage, and completion status assertions. --- .../Console/ReadLineTests.cs | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 test/unit/Elsa.Activities.UnitTests/Console/ReadLineTests.cs diff --git a/test/unit/Elsa.Activities.UnitTests/Console/ReadLineTests.cs b/test/unit/Elsa.Activities.UnitTests/Console/ReadLineTests.cs new file mode 100644 index 000000000..d89e925ae --- /dev/null +++ b/test/unit/Elsa.Activities.UnitTests/Console/ReadLineTests.cs @@ -0,0 +1,104 @@ +using Elsa.Extensions; +using Elsa.Testing.Shared; +using Elsa.Workflows; +using Microsoft.Extensions.DependencyInjection; +using NSubstitute; + +namespace Elsa.Activities.UnitTests.Console; + +/// +/// Unit tests for the activity. +/// +public class ReadLineTests +{ + private readonly TextReader _mockTextReader; + private readonly IStandardInStreamProvider _mockProvider; + + public ReadLineTests() + { + _mockTextReader = Substitute.For(); + _mockProvider = Substitute.For(); + _mockProvider.GetTextReader().Returns(_mockTextReader); + } + + [Theory(DisplayName = "ReadLine reads text from input and completes successfully")] + [InlineData("Hello, World!")] + [InlineData("Test input")] + [InlineData("")] + [InlineData(" ")] + [InlineData("\t")] + public async Task Should_Read_Text_From_Input_And_Complete(string inputText) + { + // Arrange + var readLine = new ReadLine(); + + // Act + var context = await ExecuteAsync(readLine, inputText); + + // Assert + Assert.Equal(ActivityStatus.Completed, context.Status); + var result = (string)context.GetActivityOutput(() => readLine.Result)!; + Assert.Equal(inputText, result); + } + + [Fact(DisplayName = "ReadLine uses provided stream provider")] + public async Task Should_Use_Provided_Stream_Provider() + { + // Act + await ExecuteAsync(new ReadLine()); + + // Assert + _mockProvider.Received(1).GetTextReader(); + _mockTextReader.Received(1).ReadLine(); + } + + [Fact(DisplayName = "ReadLine handles null return value from stream")] + public async Task Should_Handle_Null_Return_Value() + { + // Arrange + var readLine = new ReadLine(); + + // Act + var context = await ExecuteAsync(readLine, null); + + // Assert - The null-forgiving operator in ReadLine implementation means it expects non-null, + // but null can occur at end of stream. Verify the behavior stores null. + var result = context.GetActivityOutput(() => readLine.Result); + Assert.Null(result); + } + + [Fact(DisplayName = "ReadLine uses default provider when none is registered")] + public async Task Should_Use_Default_Provider_When_None_Registered() + { + // Arrange + var readLine = new ReadLine(); + const string expectedInput = "Default provider test"; + var originalConsoleIn = System.Console.In; + + try + { + // Redirect Console.In to our StringReader + System.Console.SetIn(new StringReader(expectedInput)); + + // Act + var context = await new ActivityTestFixture(readLine).ExecuteAsync(); + + // Assert + var result = (string)context.GetActivityOutput(() => readLine.Result)!; + Assert.Equal(expectedInput, result); + } + finally + { + // Restore original Console.In + System.Console.SetIn(originalConsoleIn); + } + } + + private Task ExecuteAsync(ReadLine readLine, string? inputText = "Test") + { + _mockTextReader.ReadLine().Returns(inputText); + return new ActivityTestFixture(readLine) + .ConfigureServices(services => services.AddSingleton(_mockProvider)) + .ExecuteAsync(); + } +}