Skip to content

Commit c09a943

Browse files
committed
feat(console): enhance ConsoleWrapper for test mode and output management
1 parent b06fa34 commit c09a943

File tree

8 files changed

+159
-131
lines changed

8 files changed

+159
-131
lines changed

.github/workflows/publish-artifacts-examples-tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ jobs:
7979
8080
# Ensure we preserve access to NuGet.org
8181
- name: Configure NuGet.org source
82+
continue-on-error: true
8283
run: |
8384
dotnet nuget add source https://api.nuget.org/v3/index.json --name nuget.org
8485

libraries/src/AWS.Lambda.Powertools.Common/Core/ConsoleWrapper.cs

Lines changed: 62 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,41 +22,77 @@ namespace AWS.Lambda.Powertools.Common;
2222
public class ConsoleWrapper : IConsoleWrapper
2323
{
2424
private static bool _override;
25+
private static TextWriter _testOutputStream;
26+
private static bool _outputResetPerformed = false;
27+
private static bool _inTestMode = false;
2528

2629
/// <inheritdoc />
2730
public void WriteLine(string message)
2831
{
29-
OverrideLambdaLogger();
30-
Console.WriteLine(message);
32+
if (_inTestMode && _testOutputStream != null)
33+
{
34+
_testOutputStream.WriteLine(message);
35+
}
36+
else
37+
{
38+
EnsureConsoleOutputOnce();
39+
Console.WriteLine(message);
40+
}
3141
}
3242

3343
/// <inheritdoc />
3444
public void Debug(string message)
3545
{
36-
OverrideLambdaLogger();
37-
System.Diagnostics.Debug.WriteLine(message);
46+
if (_inTestMode && _testOutputStream != null)
47+
{
48+
_testOutputStream.WriteLine(message);
49+
}
50+
else
51+
{
52+
EnsureConsoleOutputOnce();
53+
System.Diagnostics.Debug.WriteLine(message);
54+
}
3855
}
3956

4057
/// <inheritdoc />
4158
public void Error(string message)
4259
{
43-
if (!_override)
60+
if (_inTestMode && _testOutputStream != null)
4461
{
45-
var errordOutput = new StreamWriter(Console.OpenStandardError());
46-
errordOutput.AutoFlush = true;
47-
Console.SetError(errordOutput);
62+
_testOutputStream.WriteLine(message);
63+
}
64+
else
65+
{
66+
if (!_override)
67+
{
68+
var errordOutput = new StreamWriter(Console.OpenStandardError());
69+
errordOutput.AutoFlush = true;
70+
Console.SetError(errordOutput);
71+
}
72+
Console.Error.WriteLine(message);
4873
}
49-
50-
Console.Error.WriteLine(message);
5174
}
5275

53-
internal static void SetOut(StringWriter consoleOut)
76+
/// <summary>
77+
/// Set the ConsoleWrapper to use a different TextWriter
78+
/// This is useful for unit tests where you want to capture the output
79+
/// </summary>
80+
public static void SetOut(TextWriter consoleOut)
5481
{
82+
_testOutputStream = consoleOut;
83+
_inTestMode = true;
5584
_override = true;
5685
Console.SetOut(consoleOut);
5786
}
5887

59-
private void OverrideLambdaLogger()
88+
private static void EnsureConsoleOutputOnce()
89+
{
90+
if (_outputResetPerformed) return;
91+
OverrideLambdaLogger();
92+
_outputResetPerformed = true;
93+
}
94+
95+
private static void OverrideLambdaLogger()
6096
{
6197
if (_override)
6298
{
@@ -73,8 +109,22 @@ internal static void WriteLine(string logLevel, string message)
73109
Console.WriteLine($"{DateTime.UtcNow:yyyy-MM-ddTHH:mm:ss.fffZ}\t{logLevel}\t{message}");
74110
}
75111

112+
/// <summary>
113+
/// Reset the ConsoleWrapper to its original state
114+
/// </summary>
76115
public static void ResetForTest()
77116
{
78117
_override = false;
118+
_inTestMode = false;
119+
_testOutputStream = null;
120+
_outputResetPerformed = false;
121+
}
122+
123+
/// <summary>
124+
/// Clear the output reset flag
125+
/// </summary>
126+
public static void ClearOutputResetFlag()
127+
{
128+
_outputResetPerformed = false;
79129
}
80130
}

libraries/tests/AWS.Lambda.Powertools.BatchProcessing.Tests/Internal/BatchProcessingInternalTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public void BatchProcessing_Set_Execution_Environment_Context_SQS()
3535
var sqsBatchProcessor = new SqsBatchProcessor(conf);
3636

3737
// Assert
38-
Assert.Equal($"{Constants.FeatureContextIdentifier}/BatchProcessing/1.0.0",
38+
Assert.Equal($"{Constants.FeatureContextIdentifier}/BatchProcessing/{env.GetAssemblyVersion(this)}",
3939
env.GetEnvironmentVariable("AWS_EXECUTION_ENV"));
4040

4141
Assert.NotNull(sqsBatchProcessor);
@@ -52,7 +52,7 @@ public void BatchProcessing_Set_Execution_Environment_Context_Kinesis()
5252
var KinesisEventBatchProcessor = new KinesisEventBatchProcessor(conf);
5353

5454
// Assert
55-
Assert.Equal($"{Constants.FeatureContextIdentifier}/BatchProcessing/1.0.0",
55+
Assert.Equal($"{Constants.FeatureContextIdentifier}/BatchProcessing/{env.GetAssemblyVersion(this)}",
5656
env.GetEnvironmentVariable("AWS_EXECUTION_ENV"));
5757

5858
Assert.NotNull(KinesisEventBatchProcessor);
@@ -69,7 +69,7 @@ public void BatchProcessing_Set_Execution_Environment_Context_DynamoDB()
6969
var dynamoDbStreamBatchProcessor = new DynamoDbStreamBatchProcessor(conf);
7070

7171
// Assert
72-
Assert.Equal($"{Constants.FeatureContextIdentifier}/BatchProcessing/1.0.0",
72+
Assert.Equal($"{Constants.FeatureContextIdentifier}/BatchProcessing/{env.GetAssemblyVersion(this)}",
7373
env.GetEnvironmentVariable("AWS_EXECUTION_ENV"));
7474

7575
Assert.NotNull(dynamoDbStreamBatchProcessor);

libraries/tests/AWS.Lambda.Powertools.Common.Tests/ConsoleWrapperTests.cs

Lines changed: 89 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -6,159 +6,136 @@ namespace AWS.Lambda.Powertools.Common.Tests;
66

77
public class ConsoleWrapperTests : IDisposable
88
{
9+
private StringWriter _writer;
10+
11+
public ConsoleWrapperTests()
12+
{
13+
// Setup a new StringWriter for each test
14+
_writer = new StringWriter();
15+
// Reset static state for clean testing
16+
ConsoleWrapper.ResetForTest();
17+
}
18+
919
[Fact]
1020
public void WriteLine_Should_Write_To_Console()
1121
{
1222
// Arrange
1323
var consoleWrapper = new ConsoleWrapper();
14-
var writer = new StringWriter();
15-
ConsoleWrapper.SetOut(writer);
24+
ConsoleWrapper.SetOut(_writer);
1625

1726
// Act
1827
consoleWrapper.WriteLine("test message");
1928

2029
// Assert
21-
Assert.Equal($"test message{Environment.NewLine}", writer.ToString());
30+
Assert.Equal($"test message{Environment.NewLine}", _writer.ToString());
2231
}
2332

2433
[Fact]
2534
public void Error_Should_Write_To_Error_Console()
2635
{
2736
// Arrange
2837
var consoleWrapper = new ConsoleWrapper();
29-
var writer = new StringWriter();
30-
ConsoleWrapper.SetOut(writer);
31-
Console.SetError(writer);
38+
ConsoleWrapper.SetOut(_writer);
39+
Console.SetError(_writer);
3240

3341
// Act
3442
consoleWrapper.Error("error message");
35-
writer.Flush();
43+
_writer.Flush();
3644

3745
// Assert
38-
Assert.Equal($"error message{Environment.NewLine}", writer.ToString());
46+
Assert.Equal($"error message{Environment.NewLine}", _writer.ToString());
3947
}
4048

4149
[Fact]
4250
public void SetOut_Should_Override_Console_Output()
4351
{
4452
// Arrange
4553
var consoleWrapper = new ConsoleWrapper();
46-
var writer = new StringWriter();
47-
ConsoleWrapper.SetOut(writer);
54+
ConsoleWrapper.SetOut(_writer);
4855

4956
// Act
5057
consoleWrapper.WriteLine("test message");
5158

5259
// Assert
53-
Assert.Equal($"test message{Environment.NewLine}", writer.ToString());
60+
Assert.Equal($"test message{Environment.NewLine}", _writer.ToString());
5461
}
5562

5663
[Fact]
5764
public void OverrideLambdaLogger_Should_Override_Console_Out()
5865
{
59-
// Arrange
60-
var originalOut = Console.Out;
61-
try
62-
{
63-
var consoleWrapper = new ConsoleWrapper();
64-
65-
// Act - create a custom StringWriter and set it after constructor
66-
// but before WriteLine (which triggers OverrideLambdaLogger)
67-
var writer = new StringWriter();
68-
ConsoleWrapper.SetOut(writer);
69-
70-
consoleWrapper.WriteLine("test message");
71-
72-
// Assert
73-
Assert.Equal($"test message{Environment.NewLine}", writer.ToString());
74-
}
75-
finally
76-
{
77-
// Restore original console out
78-
ConsoleWrapper.ResetForTest();
79-
}
66+
// Arrange
67+
var consoleWrapper = new ConsoleWrapper();
68+
ConsoleWrapper.SetOut(_writer);
69+
70+
// Act
71+
consoleWrapper.WriteLine("test message");
72+
73+
// Assert
74+
Assert.Equal($"test message{Environment.NewLine}", _writer.ToString());
75+
}
76+
77+
[Fact]
78+
public void WriteLine_WritesMessageToConsole()
79+
{
80+
// Arrange
81+
var consoleWrapper = new ConsoleWrapper();
82+
ConsoleWrapper.SetOut(_writer);
83+
84+
// Act
85+
consoleWrapper.WriteLine("Test message");
86+
87+
// Assert
88+
var output = _writer.ToString();
89+
Assert.Contains("Test message", output);
90+
}
91+
92+
[Fact]
93+
public void SetOut_OverridesConsoleOutput()
94+
{
95+
// Act
96+
ConsoleWrapper.SetOut(_writer);
97+
Console.WriteLine("Test override");
98+
99+
// Assert
100+
var output = _writer.ToString();
101+
Assert.Contains("Test override", output);
80102
}
81-
103+
82104
[Fact]
83-
public void WriteLine_WritesMessageToConsole()
84-
{
85-
// Arrange
86-
var consoleWrapper = new ConsoleWrapper();
87-
var originalOutput = Console.Out;
88-
using var stringWriter = new StringWriter();
89-
ConsoleWrapper.SetOut(stringWriter);
90-
91-
try
92-
{
93-
// Act
94-
consoleWrapper.WriteLine("Test message");
95-
96-
// Assert
97-
var output = stringWriter.ToString();
98-
Assert.Contains("Test message", output);
99-
}
100-
finally
101-
{
102-
// Restore original output
103-
ConsoleWrapper.ResetForTest();
104-
}
105-
}
105+
public void StaticWriteLine_FormatsLogMessageCorrectly()
106+
{
107+
// Arrange
108+
ConsoleWrapper.SetOut(_writer);
109+
110+
// Act - Using reflection to call internal static method
111+
typeof(ConsoleWrapper)
112+
.GetMethod("WriteLine", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static, null, new[] { typeof(string), typeof(string) }, null)
113+
?.Invoke(null, new object[] { "INFO", "Test log message" });
114+
115+
// Assert
116+
var output = _writer.ToString();
117+
Assert.Matches(@"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z\tINFO\tTest log message", output);
118+
}
119+
120+
[Fact]
121+
public void ClearOutputResetFlag_ResetsFlag()
122+
{
123+
// Arrange
124+
var consoleWrapper = new ConsoleWrapper();
125+
ConsoleWrapper.SetOut(_writer);
106126

107-
[Fact]
108-
public void SetOut_OverridesConsoleOutput()
109-
{
110-
// Arrange
111-
var originalOutput = Console.Out;
112-
using var stringWriter = new StringWriter();
113-
114-
try
115-
{
116-
// Act
117-
typeof(ConsoleWrapper)
118-
.GetMethod("SetOut", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)
119-
?.Invoke(null, new object[] { stringWriter });
120-
121-
Console.WriteLine("Test override");
122-
123-
// Assert
124-
var output = stringWriter.ToString();
125-
Assert.Contains("Test override", output);
126-
}
127-
finally
128-
{
129-
// Restore original output
130-
ConsoleWrapper.ResetForTest();
131-
}
132-
}
127+
// Act
128+
consoleWrapper.WriteLine("First message"); // Should set the reset flag
129+
ConsoleWrapper.ClearOutputResetFlag();
130+
consoleWrapper.WriteLine("Second message"); // Should set it again
133131

134-
[Fact]
135-
public void StaticWriteLine_FormatsLogMessageCorrectly()
136-
{
137-
// Arrange
138-
var originalOutput = Console.Out;
139-
using var stringWriter = new StringWriter();
140-
ConsoleWrapper.SetOut(stringWriter);
141-
142-
try
143-
{
144-
// Act
145-
typeof(ConsoleWrapper)
146-
.GetMethod("WriteLine", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static, null, new[] { typeof(string), typeof(string) }, null)
147-
?.Invoke(null, new object[] { "INFO", "Test log message" });
148-
149-
// Assert
150-
var output = stringWriter.ToString();
151-
Assert.Matches(@"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z\tINFO\tTest log message", output);
152-
}
153-
finally
154-
{
155-
// Restore original output
156-
ConsoleWrapper.ResetForTest();
157-
}
158-
}
159-
160-
public void Dispose()
161-
{
162-
ConsoleWrapper.ResetForTest();
163-
}
132+
// Assert
133+
Assert.Equal($"First message{Environment.NewLine}Second message{Environment.NewLine}", _writer.ToString());
134+
}
135+
136+
public void Dispose()
137+
{
138+
ConsoleWrapper.ResetForTest();
139+
_writer?.Dispose();
140+
}
164141
}

0 commit comments

Comments
 (0)