Skip to content
This repository was archived by the owner on Aug 18, 2021. It is now read-only.

Commit 44a81f7

Browse files
committed
feat(ServiceBus): added unit tests
Added some tests that should test the general behavior of ServiceBus.
1 parent 8788ca5 commit 44a81f7

File tree

6 files changed

+482
-19
lines changed

6 files changed

+482
-19
lines changed

src/Liquid.Activation/Worker/LightWorker.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public abstract class LightWorker : LightBackgroundTask, ILightWorker
2525
protected readonly static Dictionary<MethodInfo, QueueAttribute> _queues = new Dictionary<MethodInfo, QueueAttribute>();
2626
protected readonly static Dictionary<MethodInfo, TopicAttribute> _topics = new Dictionary<MethodInfo, TopicAttribute>();
2727
private readonly List<string> _inputValidationErrors = new List<string>();
28-
protected ILightTelemetry Telemetry { get; } = Workbench.Instance.Telemetry != null ? (ILightTelemetry)Workbench.Instance.Telemetry.CloneService() : null;
28+
protected ILightTelemetry Telemetry => Workbench.Instance.Telemetry;
2929
protected ILightCache Cache => Workbench.Instance.Cache;
3030
//Instance of CriticHandler to inject on the others classes
3131
private readonly CriticHandler _criticHandler = new CriticHandler();

src/Liquid.OnAzure/Liquid.OnAzure.csproj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
<DebugType>full</DebugType>
1616
<DebugSymbols>true</DebugSymbols>
1717
</PropertyGroup>
18+
<ItemGroup>
19+
<AdditionalFiles Include="..\..\stylecop.json" Link="stylecop.json" />
20+
</ItemGroup>
1821
<ItemGroup>
1922
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.7.1" />
2023
<PackageReference Include="Microsoft.ApplicationInsights.Kubernetes" Version="1.1.1" />
@@ -27,6 +30,10 @@
2730
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="2.2.0" />
2831
<PackageReference Include="Microsoft.Extensions.Caching.Redis" Version="2.2.0" />
2932
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
33+
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.113">
34+
<PrivateAssets>all</PrivateAssets>
35+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
36+
</PackageReference>
3037
<PackageReference Include="WindowsAzure.Storage" Version="9.3.3" />
3138
</ItemGroup>
3239
<ItemGroup>

src/Liquid.OnAzure/MessageBuses/ServiceBus.cs

Lines changed: 165 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,125 @@
1-
using Liquid.Base.Interfaces;
1+
// Copyright (c) Avanade Inc. All rights reserved.
2+
// Licensed under the MIT License. See LICENSE in the project root for license information.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Reflection;
7+
using System.Threading.Tasks;
8+
using Liquid.Activation;
29
using Liquid.Domain;
310
using Liquid.Domain.Base;
4-
using Liquid.Activation;
511
using Liquid.Runtime.Configuration.Base;
612
using Liquid.Runtime.Telemetry;
713
using Microsoft.Azure.ServiceBus;
8-
using System;
9-
using System.Collections.Generic;
10-
using System.Reflection;
11-
using System.Text;
12-
using System.Threading.Tasks;
1314

1415
namespace Liquid.OnAzure
1516
{
1617
/// <summary>
17-
/// Implementation of the communication component between queues and topics of the Azure, this class is specific to azure
18+
/// Defines an object capable of creating instances of <see cref="IQueueClient"/>.
19+
/// </summary>
20+
public interface IQueueClientFactory
21+
{
22+
/// <summary>
23+
/// Creates a new instance of <see cref="IQueueClient"/>.
24+
/// </summary>
25+
/// <param name="connectionString">The connection string for the client.</param>
26+
/// <param name="queueName">The name of the queue.</param>
27+
/// <param name="receiveMode">The receive mode that the client will connect to the queue.</param>
28+
/// <returns>A new instance of <see cref="IQueueClient"/>.</returns>
29+
IQueueClient CreateClient(string connectionString, string queueName, ReceiveMode receiveMode);
30+
}
31+
32+
/// <summary>
33+
/// Defines an object capable of creating instances of <see cref="ISubscriptionClient"/>.
34+
/// </summary>
35+
public interface ISubscriptionClientFactory
36+
{
37+
/// <summary>
38+
/// Creates a new instance of <see cref="ISubscriptionClient"/>.
39+
/// </summary>
40+
/// <param name="connectionString">The connection string for the client.</param>
41+
/// <param name="topicName">The name of the topic to connect to.</param>
42+
/// <param name="subscriptionName">Identifies the subscription to this topic.</param>
43+
/// <param name="receiveMode">The receive mode that the client will connect to the queue.</param>
44+
/// <returns>A new instance of <see cref="ISubscriptionClient"/>.</returns>
45+
ISubscriptionClient CreateClient(string connectionString, string topicName, string subscriptionName, ReceiveMode receiveMode);
46+
}
47+
48+
/// <summary>
49+
/// Configuration source for <see cref="ServiceBus"/>.
50+
/// </summary>
51+
// TODO: should remove this class once we move to .NET configuration system
52+
public interface IServiceBusConfigurationProvider
53+
{
54+
/// <summary>
55+
/// Gets the configuration for a <see cref="ServiceBus"/>.
56+
/// </summary>
57+
/// <returns>
58+
/// The current configuration for a service bus.
59+
/// </returns>
60+
ServiceBusConfiguration GetConfiguration();
61+
62+
/// <summary>
63+
/// Gets the configuration for a <see cref="ServiceBus"/>.
64+
/// </summary>
65+
/// <param name="connectionName">
66+
/// Identifies which connection should be retrieved from the file.
67+
/// </param>
68+
/// <returns>
69+
/// The current configuration for a service bus.
70+
/// </returns>
71+
ServiceBusConfiguration GetConfiguration(string connectionName);
72+
}
73+
74+
/// <summary>
75+
/// Implementation of the communication component between queues and topics of the Azure, this class is specific to azure.
1876
/// </summary>
1977
public class ServiceBus : LightWorker, IWorkbenchService
2078
{
79+
/// <summary>
80+
/// Factory used to create a <see cref="IQueueClient"/>.
81+
/// </summary>
82+
private readonly IQueueClientFactory _queueClientFactory = new DefaultQueueClientFactory();
83+
84+
/// <summary>
85+
/// Factory used to create a <see cref="ISubscriptionClient"/>.
86+
/// </summary>
87+
private readonly ISubscriptionClientFactory _subscriptionClientFactory = new DefaultSubscriptionClientFactory();
88+
89+
/// <summary>
90+
/// Service that retrives a <see cref="ServiceBusConfiguration"/>.
91+
/// </summary>
92+
private readonly IServiceBusConfigurationProvider _configurationProvider = new DefaultServiceBusConfigurationProvider();
93+
94+
/// <summary>
95+
/// Initializes a new instance of the <see cref="ServiceBus"/> class.
96+
/// </summary>
97+
public ServiceBus()
98+
{
99+
}
100+
101+
/// <summary>
102+
/// Initializes a new instance of the <see cref="ServiceBus"/> class.
103+
/// </summary>
104+
/// <param name="queueClientFactory">
105+
/// Dependency. Used to obtain new instances of a <see cref="IQueueClient"/>.
106+
/// </param>
107+
/// <param name="subscriptionClientFactory">
108+
/// Dependency. Used to obtain new instances of a <see cref="ISubscriptionClient"/>.
109+
/// </param>
110+
/// <param name="configurationProvider">
111+
/// Dependency. Used to retrieve a configuration for this class.
112+
/// </param>
113+
public ServiceBus(
114+
IQueueClientFactory queueClientFactory,
115+
ISubscriptionClientFactory subscriptionClientFactory,
116+
IServiceBusConfigurationProvider configurationProvider)
117+
{
118+
_queueClientFactory = queueClientFactory ?? throw new ArgumentNullException(nameof(queueClientFactory));
119+
_subscriptionClientFactory = subscriptionClientFactory ?? throw new ArgumentNullException(nameof(subscriptionClientFactory));
120+
_configurationProvider = configurationProvider ?? throw new ArgumentNullException(nameof(configurationProvider));
121+
}
122+
21123
/// <summary>
22124
/// Implementation of the start process queue and process topic. It must be called parent before start processes.
23125
/// </summary>
@@ -36,22 +138,22 @@ public override void Initialize()
36138
/// <returns>StringConnection of the ServiceBus</returns>
37139
private string GetConnection<T>(KeyValuePair<MethodInfo, T> item)
38140
{
39-
MethodInfo method = item.Key;
40-
string connectionKey = GetKeyConnection(method);
41-
ServiceBusConfiguration config = null;
141+
var method = item.Key;
142+
var connectionKey = GetKeyConnection(method);
143+
144+
ServiceBusConfiguration config;
42145
if (string.IsNullOrEmpty(connectionKey)) // Load specific settings if provided
43146
{
44-
config = LightConfigurator.Config<ServiceBusConfiguration>($"{nameof(ServiceBus)}");
147+
config = _configurationProvider.GetConfiguration();//LightConfigurator.Config<ServiceBusConfiguration>($"{nameof(ServiceBus)}");
45148
}
46149
else
47150
{
48-
config = LightConfigurator.Config<ServiceBusConfiguration>($"{nameof(ServiceBus)}_{connectionKey}");
151+
config = _configurationProvider.GetConfiguration(connectionKey);//LightConfigurator.Config<ServiceBusConfiguration>($"{nameof(ServiceBus)}_{connectionKey}");
49152
}
50153

51154
return config.ConnectionString;
52155
}
53156

54-
55157
/// <summary>
56158
/// If an error occurs in the processing, this method going to called
57159
/// </summary>
@@ -80,7 +182,7 @@ public void ProcessQueue()
80182
int takeQuantity = queue.Value.TakeQuantity;
81183

82184
//Register Trace on the telemetry
83-
QueueClient queueReceiver = new QueueClient(GetConnection(queue), queueName, receiveMode);
185+
var queueReceiver = _queueClientFactory.CreateClient(GetConnection(queue), queueName, receiveMode);
84186

85187
//Register the method to process receive message
86188
//The RegisterMessageHandler is validate for all register exist on the queue, without need loop for items
@@ -132,14 +234,17 @@ private void ProcessSubscription()
132234
string topicName = topic.Value.TopicName;
133235
string subscriptName = topic.Value.Subscription;
134236
ReceiveMode receiveMode = ReceiveMode.PeekLock;
237+
135238
if (topic.Value.DeleteAfterRead)
136239
{
137240
receiveMode = ReceiveMode.ReceiveAndDelete;
138241
}
242+
139243
int takeQuantity = topic.Value.TakeQuantity;
140244

141245
//Register Trace on the telemetry
142-
SubscriptionClient subscriptionClient = new SubscriptionClient(GetConnection(topic), topicName, subscriptName, receiveMode, null);
246+
var subscriptionClient = _subscriptionClientFactory.CreateClient(
247+
GetConnection(topic), topicName, subscriptName, receiveMode);
143248

144249
//Register the method to process receive message
145250
//The RegisterMessageHandler is validate for all register exist on the queue, without need loop for items
@@ -208,5 +313,49 @@ protected override Task ProcessAsync()
208313
{
209314
throw new NotImplementedException();
210315
}
316+
317+
/// <summary>
318+
/// Default implementation for <see cref="IQueueClientFactory"/>,
319+
/// creates instances of <see cref="IQueueClient"/>.
320+
/// </summary>
321+
private class DefaultQueueClientFactory : IQueueClientFactory
322+
{
323+
/// <inheritdoc/>
324+
public IQueueClient CreateClient(string connectionString, string queueName, ReceiveMode receiveMode)
325+
{
326+
return new QueueClient(connectionString, queueName, receiveMode);
327+
}
328+
}
329+
330+
/// <summary>
331+
/// Default implementation for <see cref="ISubscriptionClientFactory"/>,
332+
/// creates instances of <see cref="SubscriptionClient"/>.
333+
/// </summary>
334+
private class DefaultSubscriptionClientFactory : ISubscriptionClientFactory
335+
{
336+
/// <inheritdoc/>
337+
public ISubscriptionClient CreateClient(string connectionString, string topicName, string subscriptionName, ReceiveMode mode)
338+
{
339+
return new SubscriptionClient(connectionString, topicName, subscriptionName, mode, null);
340+
}
341+
}
342+
343+
/// <summary>
344+
/// Retrieves configuration using <see cref="LightConfigurator"/>.
345+
/// </summary>
346+
private class DefaultServiceBusConfigurationProvider : IServiceBusConfigurationProvider
347+
{
348+
/// <inheritdoc/>
349+
public ServiceBusConfiguration GetConfiguration()
350+
{
351+
return LightConfigurator.Config<ServiceBusConfiguration>($"{nameof(ServiceBus)}");
352+
}
353+
354+
/// <inheritdoc/>
355+
public ServiceBusConfiguration GetConfiguration(string connectionKey)
356+
{
357+
return LightConfigurator.Config<ServiceBusConfiguration>($"{nameof(ServiceBus)}_{connectionKey}");
358+
}
359+
}
211360
}
212361
}

test/Liquid.OnAzure.Tests/AzureBlobTests.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ public class AzureBlobTests : IDisposable
3939

4040
public AzureBlobTests()
4141
{
42-
Workbench.Instance.Reset();
43-
4442
Workbench.Instance.AddToCache(WorkbenchServiceType.Repository, _fakeLightRepository);
4543

4644
_sut = new AzureBlob(new MediaStorageConfiguration
@@ -266,6 +264,7 @@ protected virtual void Dispose(bool isDisposing)
266264
{
267265
_stream?.Dispose();
268266
_lightAttachment?.Dispose();
267+
Workbench.Instance.Reset();
269268
}
270269
}
271270

test/Liquid.OnAzure.Tests/Liquid.OnAzure.Tests.csproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
<ItemGroup>
1414
<PackageReference Include="AutoFixture.AutoNSubstitute" Version="4.11.0" />
1515
<PackageReference Include="AutoFixture.Xunit2" Version="4.11.0" />
16+
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8">
17+
<PrivateAssets>all</PrivateAssets>
18+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
19+
</PackageReference>
1620
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
1721
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.113">
1822
<PrivateAssets>all</PrivateAssets>
@@ -24,6 +28,7 @@
2428
</ItemGroup>
2529

2630
<ItemGroup>
31+
<ProjectReference Include="..\..\src\Liquid.Base\Liquid.Base.csproj" />
2732
<ProjectReference Include="..\..\src\Liquid.OnAzure\Liquid.OnAzure.csproj" />
2833
<ProjectReference Include="..\Liquid.Tests\Liquid.Tests.csproj" />
2934
</ItemGroup>

0 commit comments

Comments
 (0)