Skip to content

Commit 71a5f54

Browse files
committed
Introduce async methods in application services
1 parent d0490f7 commit 71a5f54

File tree

11 files changed

+161
-8
lines changed

11 files changed

+161
-8
lines changed

RealTimeWeatherMonitoringApp/Application/Interfaces/IDataReceiver.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ namespace RealTimeWeatherMonitoringApp.Application.Interfaces;
77
public interface IDataReceiver<in TReceived>
88
{
99
void Receive(TReceived? data);
10+
11+
Task ReceiveAsync(TReceived? data);
1012
}

RealTimeWeatherMonitoringApp/Application/Interfaces/Service/IAutoParsingService.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,9 @@ public interface IAutoParsingService<TResult>
1919
/// <returns>A <see cref="ParsingResult{TResult}"/> object that encapsulates the result of the parsing operation,
2020
/// indicating success or failure, and containing the parsed <typeparamref name="TResult"/> if successful.</returns>
2121
ParsingResult<TResult> AutoParse(string input);
22+
23+
/// <summary>
24+
/// Asynchronous version of <see cref="AutoParse"/>
25+
/// </summary>
26+
Task<ParsingResult<TResult>> AutoParseAsync(string input);
2227
}

RealTimeWeatherMonitoringApp/Application/Interfaces/Service/IDataProcessingService.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,9 @@ public interface IDataProcessingService<TData>
1515
/// <returns>A <see cref="ParsingResult{TData}"/> object that encapsulates the result of the parsing operation,
1616
/// indicating success or failure, and containing the parsed <see cref="TData"/> if successful.</returns>
1717
ParsingResult<TData> Process(string input);
18+
19+
/// <summary>
20+
/// Asynchronous version of <see cref="Process"/>
21+
/// </summary>
22+
Task<ParsingResult<TData>> ProcessAsync(string input);
1823
}

RealTimeWeatherMonitoringApp/Application/Service/AutoParsingService.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,7 @@ public ParsingResult<TResult> AutoParse(string input)
2323

2424
return new ParsingResult<TResult>(false, $"No valid parsing strategy was found for input '{input}'");
2525
}
26+
27+
public async Task<ParsingResult<TResult>> AutoParseAsync(string input) =>
28+
await Task.Run(() => AutoParse(input));
2629
}

RealTimeWeatherMonitoringApp/Application/Service/DataProcessingService.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,12 @@ public ParsingResult<TData> Process(string input)
2121
if (result.Success) _receiver.Receive(result.Data);
2222
return result;
2323
}
24+
25+
public async Task<ParsingResult<TData>> ProcessAsync(string input)
26+
{
27+
var result = await _autoParsingService.AutoParseAsync(input);
28+
if (result.Success)
29+
await _receiver.ReceiveAsync(result.Data);
30+
return result;
31+
}
2432
}

RealTimeWeatherMonitoringApp/Application/Service/MonitoringService.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,7 @@ public class MonitoringService<TData> : IDataReceiver<TData>, IDataChangeNotifie
1212
public void Receive(TData? data) =>
1313
OnDataChange?.Invoke(this, new DataChangeEventArgs<TData>(data));
1414

15+
public async Task ReceiveAsync(TData? data) => await Task.Run(() => Receive(data));
16+
1517
public event EventHandler<DataChangeEventArgs<TData>>? OnDataChange;
1618
}

RealTimeWeatherMonitoringApp/Presentation/Controller/UserController.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public UserController(
1616
_weatherDataProcessor = weatherDataProcessor;
1717
}
1818

19-
public void Start()
19+
public async Task Start()
2020
{
2121
_botNotificationService.OnBotNotification += (_, args) =>
2222
Console.WriteLine($"\n{args.BotName}: {args.Message}");
@@ -34,7 +34,7 @@ public void Start()
3434
var input = Console.ReadLine() ?? string.Empty;
3535
if (input.Equals("q", StringComparison.CurrentCultureIgnoreCase)) break;
3636

37-
var result = _weatherDataProcessor.Process(input);
37+
var result = await _weatherDataProcessor.ProcessAsync(input);
3838
if (result.Fail) Console.WriteLine(result.Message);
3939
}
4040
}

RealTimeWeatherMonitoringApp/Presentation/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@
77

88
// Start
99
provider.GetRequiredService<ServerController>().Start();
10-
provider.GetRequiredService<UserController>().Start();
10+
await provider.GetRequiredService<UserController>().Start();

RealTimeWeatherMonitoringTest/Application/Service/AutoParsingServiceShould.cs

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ public void AutoParse_NoParsingStrategyWorks_ReturnFailResult(
1717
AutoParsingService<TestData> autoParsingService)
1818
{
1919
foreach (var mock in strategyMocks)
20+
{
2021
autoParsingService.AddStrategy(mock.Object);
22+
mock.Setup(s => s.TryParse(input, out It.Ref<TestData?>.IsAny)).Returns(false);
23+
}
2124

2225
var result = autoParsingService.AutoParse(input);
2326

@@ -26,6 +29,25 @@ public void AutoParse_NoParsingStrategyWorks_ReturnFailResult(
2629
result.Data.Should().BeNull();
2730
}
2831

32+
[Theory, AutoMoqData]
33+
public async Task AutoParseAsync_NoParsingStrategyWorks_ReturnFailResult(
34+
string input,
35+
List<Mock<IParsingStrategy<TestData>>> strategyMocks,
36+
AutoParsingService<TestData> autoParsingService)
37+
{
38+
foreach (var mock in strategyMocks)
39+
{
40+
autoParsingService.AddStrategy(mock.Object);
41+
mock.Setup(s => s.TryParse(input, out It.Ref<TestData?>.IsAny)).Returns(false);
42+
}
43+
44+
var result = await autoParsingService.AutoParseAsync(input);
45+
46+
result.Should().NotBeNull();
47+
result.Success.Should().BeFalse();
48+
result.Data.Should().BeNull();
49+
}
50+
2951
[Theory, AutoMoqData]
3052
public void AutoParse_AStrategyWorks_ReturnSuccessResult(
3153
string input,
@@ -43,23 +65,62 @@ public void AutoParse_AStrategyWorks_ReturnSuccessResult(
4365
result.Data.Should().BeSameAs(resultData);
4466
}
4567

68+
[Theory, AutoMoqData]
69+
public async Task AutoParseAsync_AStrategyWorks_ReturnSuccessResult(
70+
string input,
71+
TestData? resultData,
72+
Mock<IParsingStrategy<TestData>> strategyMock,
73+
AutoParsingService<TestData> autoParsingService)
74+
{
75+
autoParsingService.AddStrategy(strategyMock.Object);
76+
strategyMock.Setup(s => s.TryParse(input, out resultData)).Returns(true);
77+
78+
var result = await autoParsingService.AutoParseAsync(input);
79+
80+
result.Should().NotBeNull();
81+
result.Success.Should().BeTrue();
82+
result.Data.Should().BeSameAs(resultData);
83+
}
84+
4685
[Theory, AutoMoqData]
4786
public void AutoParse_MultipleStrategiesWork_UseFirstOne(
4887
string input,
88+
TestData? firstResultData,
89+
TestData? secondResultData,
4990
Mock<IParsingStrategy<TestData>> firstStrategyMock,
5091
Mock<IParsingStrategy<TestData>> secondStrategyMock,
5192
AutoParsingService<TestData> autoParsingService)
5293
{
5394
autoParsingService.AddStrategy(firstStrategyMock.Object);
5495
autoParsingService.AddStrategy(secondStrategyMock.Object);
5596

56-
TestData? dummy = null;
57-
firstStrategyMock.Setup(s => s.TryParse(input, out dummy)).Returns(true);
58-
secondStrategyMock.Setup(s => s.TryParse(input, out dummy)).Returns(true);
97+
firstStrategyMock.Setup(s => s.TryParse(input, out firstResultData)).Returns(true);
98+
secondStrategyMock.Setup(s => s.TryParse(input, out secondResultData)).Returns(true);
5999

60100
autoParsingService.AutoParse(input);
61101

62-
firstStrategyMock.Verify(s => s.TryParse(input, out dummy), Times.Once);
63-
secondStrategyMock.Verify(s => s.TryParse(input, out dummy), Times.Never);
102+
firstStrategyMock.Verify(s => s.TryParse(input, out firstResultData), Times.Once);
103+
secondStrategyMock.Verify(s => s.TryParse(input, out secondResultData), Times.Never);
104+
}
105+
106+
[Theory, AutoMoqData]
107+
public async Task AutoParseAsync_MultipleStrategiesWork_UseFirstOne(
108+
string input,
109+
TestData? firstResultData,
110+
TestData? secondResultData,
111+
Mock<IParsingStrategy<TestData>> firstStrategyMock,
112+
Mock<IParsingStrategy<TestData>> secondStrategyMock,
113+
AutoParsingService<TestData> autoParsingService)
114+
{
115+
autoParsingService.AddStrategy(firstStrategyMock.Object);
116+
autoParsingService.AddStrategy(secondStrategyMock.Object);
117+
118+
firstStrategyMock.Setup(s => s.TryParse(input, out firstResultData)).Returns(true);
119+
secondStrategyMock.Setup(s => s.TryParse(input, out secondResultData)).Returns(true);
120+
121+
await autoParsingService.AutoParseAsync(input);
122+
123+
firstStrategyMock.Verify(s => s.TryParse(input, out firstResultData), Times.Once);
124+
secondStrategyMock.Verify(s => s.TryParse(input, out secondResultData), Times.Never);
64125
}
65126
}

RealTimeWeatherMonitoringTest/Application/Service/DataProcessingServiceShould.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,25 @@ public void Process_SuccessfulParsing_SendDataToReceiver(
3232
result.Should().BeSameAs(parsingResult);
3333
}
3434

35+
[Theory, AutoMoqData]
36+
public async Task ProcessAsync_SuccessfulAsyncParsing_SendDataToReceiverAsync(
37+
string goodInput,
38+
ParsingResult<TestData> parsingResult,
39+
[Frozen] Mock<IAutoParsingService<TestData>> autoParsingServiceMock,
40+
[Frozen] Mock<IDataReceiver<TestData>> dataReceiverMock,
41+
DataProcessingService<TestData> dataProcessingService)
42+
{
43+
parsingResult.Success = true;
44+
autoParsingServiceMock
45+
.Setup(s => s.AutoParseAsync(goodInput))
46+
.ReturnsAsync(parsingResult);
47+
48+
var result = await dataProcessingService.ProcessAsync(goodInput);
49+
50+
dataReceiverMock.Verify(r => r.ReceiveAsync(parsingResult.Data), Times.Once);
51+
result.Should().BeSameAs(parsingResult);
52+
}
53+
3554
[Theory, AutoMoqData]
3655
public void Process_FailedParsing_NotSendToReceiver(
3756
string badInput,
@@ -50,4 +69,23 @@ public void Process_FailedParsing_NotSendToReceiver(
5069
dataReceiverMock.Verify(r => r.Receive(It.IsAny<TestData>()), Times.Never);
5170
result.Should().BeSameAs(parsingResult);
5271
}
72+
73+
[Theory, AutoMoqData]
74+
public async Task ProcessAsync_FailedAsyncParsing_NotSendToReceiverAsync(
75+
string badInput,
76+
ParsingResult<TestData> parsingResult,
77+
[Frozen] Mock<IAutoParsingService<TestData>> autoParsingServiceMock,
78+
[Frozen] Mock<IDataReceiver<TestData>> dataReceiverMock,
79+
DataProcessingService<TestData> dataProcessingService)
80+
{
81+
parsingResult.Success = false;
82+
autoParsingServiceMock
83+
.Setup(s => s.AutoParseAsync(badInput))
84+
.ReturnsAsync(parsingResult);
85+
86+
var result = await dataProcessingService.ProcessAsync(badInput);
87+
88+
dataReceiverMock.Verify(r => r.ReceiveAsync(It.IsAny<TestData>()), Times.Never);
89+
result.Should().BeSameAs(parsingResult);
90+
}
5391
}

0 commit comments

Comments
 (0)