Skip to content

Commit 6939a33

Browse files
committed
adding support for ExpectInstance in DependencyValidator
1 parent 4db83a0 commit 6939a33

File tree

5 files changed

+121
-13
lines changed

5 files changed

+121
-13
lines changed

src/WebJobs.Script.WebHost/DependencyInjection/DependencyValidator/DependencyValidator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ private static string FormatServiceDescriptor(ServiceDescriptor descriptor)
8888

8989
if (descriptor.ImplementationInstance != null)
9090
{
91-
format += $", {nameof(descriptor.ImplementationInstance)}: {descriptor.ImplementationInstance}";
91+
format += $", {nameof(descriptor.ImplementationInstance)}: {descriptor.ImplementationInstance.GetType()}";
9292
}
9393

9494
if (descriptor.ImplementationType != null)

src/WebJobs.Script.WebHost/DependencyInjection/DependencyValidator/ExpectedDependencyBuilder.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ public void ExpectNone<TService>()
6868
AddNewMatch<TService>(match);
6969
}
7070

71+
public void ExpectInstance<TService, TExpectedType>()
72+
{
73+
ServiceMatch match = ServiceMatch.CreateMatch<TService>();
74+
AddNewMatch<TService>(match);
75+
match.AddInstance<TExpectedType>();
76+
}
77+
7178
public ExpectedCollectionBuilder ExpectCollection<TService>()
7279
{
7380
ServiceMatch match = ServiceMatch.CreateCollectionMatch<TService>();

src/WebJobs.Script.WebHost/DependencyInjection/DependencyValidator/ServiceMatch.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,13 @@ public void AddFactory<TFactoryType>(ServiceLifetime lifetime)
108108
Add(desc);
109109
}
110110

111+
public void AddInstance<TInstanceType>()
112+
{
113+
// Hijack the instance property pass in the expected type
114+
ServiceDescriptor desc = new ServiceDescriptor(ServiceType, typeof(TInstanceType));
115+
Add(desc);
116+
}
117+
111118
private void Add(ServiceDescriptor desc)
112119
{
113120
if (_match == MatchType.Single && _requiredDescriptors.Any())
@@ -168,7 +175,8 @@ public IEnumerable<InvalidServiceDescriptor> FindInvalidServices(IServiceCollect
168175

169176
private static bool IsMatch(ServiceDescriptor expected, ServiceDescriptor registered)
170177
{
171-
bool factoryMatches = false;
178+
bool factoryMatches = expected.ImplementationFactory == registered.ImplementationFactory;
179+
bool instanceMatches = expected.ImplementationInstance == registered.ImplementationInstance;
172180

173181
if (expected.ImplementationFactory != null && registered.ImplementationFactory != null)
174182
{
@@ -178,13 +186,16 @@ private static bool IsMatch(ServiceDescriptor expected, ServiceDescriptor regist
178186
Assembly expectedAssembly = (Assembly)expected.ImplementationFactory(null);
179187
factoryMatches = expectedAssembly == registered.ImplementationFactory.GetMethodInfo().DeclaringType.Assembly;
180188
}
181-
else
189+
else if (expected.ImplementationInstance != null && registered.ImplementationInstance != null)
182190
{
183-
factoryMatches = expected.ImplementationFactory == registered.ImplementationFactory;
191+
// A non-null ImplementationInstance signals we expect this to be an Instance, and we've
192+
// stored the type we expect in the expected ServiceDescriptor.
193+
Type expectedInstanceType = expected.ImplementationInstance as Type;
194+
instanceMatches = expectedInstanceType == registered.ImplementationInstance.GetType();
184195
}
185196

186197
return factoryMatches &&
187-
expected.ImplementationInstance == registered.ImplementationInstance &&
198+
instanceMatches &&
188199
expected.ImplementationType == registered.ImplementationType &&
189200
expected.Lifetime == registered.Lifetime &&
190201
expected.ServiceType == registered.ServiceType;

test/WebJobs.Script.Tests/Configuration/DefaultDependencyValidatorTests.cs

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Threading;
99
using System.Threading.Tasks;
1010
using Microsoft.AspNetCore.Hosting;
11+
using Microsoft.Azure.WebJobs.Script.Diagnostics;
1112
using Microsoft.Azure.WebJobs.Script.Eventing;
1213
using Microsoft.Azure.WebJobs.Script.WebHost;
1314
using Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection;
@@ -39,6 +40,7 @@ public async Task Validator_InvalidServices_LogsError()
3940
{
4041
s.AddSingleton<IHostedService, MyHostedService>();
4142
s.AddSingleton<IScriptEventManager, MyScriptEventManager>();
43+
s.AddSingleton<IMetricsLogger>(new MyMetricsLogger());
4244

4345
// Try removing system logger
4446
var descriptor = s.Single(p => p.ImplementationType == typeof(SystemLoggerProvider));
@@ -48,9 +50,10 @@ public async Task Validator_InvalidServices_LogsError()
4850
Assert.NotNull(invalidServicesMessage);
4951

5052
IEnumerable<string> messageLines = invalidServicesMessage.Exception.Message.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries).Select(p => p.Trim());
51-
Assert.Equal(4, messageLines.Count());
53+
Assert.Equal(5, messageLines.Count());
5254
Assert.Contains(messageLines, p => p.StartsWith("[Invalid]") && p.EndsWith(nameof(MyHostedService)));
5355
Assert.Contains(messageLines, p => p.StartsWith("[Invalid]") && p.EndsWith(nameof(MyScriptEventManager)));
56+
Assert.Contains(messageLines, p => p.StartsWith("[Invalid]") && p.EndsWith(nameof(MyMetricsLogger)));
5457
Assert.Contains(messageLines, p => p.StartsWith("[Missing]") && p.EndsWith(nameof(SystemLoggerProvider)));
5558
}
5659

@@ -79,13 +82,6 @@ private async Task<LogMessage> RunTest(Action<IServiceCollection> configureWebHo
7982
})
8083
.ConfigureServices(s =>
8184
{
82-
s.AddSingleton<IConfigureBuilder<ILoggingBuilder>>(new DelegatedConfigureBuilder<ILoggingBuilder>(b =>
83-
{
84-
b.AddProvider(loggerProvider);
85-
86-
configureJobHost?.Invoke(b.Services);
87-
}));
88-
8985
string uniqueTestRootPath = Path.Combine(Path.GetTempPath(), "FunctionsTest", "DependencyValidatorTests");
9086

9187
s.PostConfigureAll<ScriptApplicationHostOptions>(o =>
@@ -97,6 +93,14 @@ private async Task<LogMessage> RunTest(Action<IServiceCollection> configureWebHo
9793
});
9894

9995
configureWebHost?.Invoke(s);
96+
})
97+
.ConfigureScriptHostLogging(b =>
98+
{
99+
b.AddProvider(loggerProvider);
100+
})
101+
.ConfigureScriptHostServices(b =>
102+
{
103+
configureJobHost?.Invoke(b);
100104
});
101105

102106
using (var host = builder.Build())
@@ -143,6 +147,31 @@ public IDisposable Subscribe(IObserver<ScriptEvent> observer)
143147
}
144148
}
145149

150+
private class MyMetricsLogger : IMetricsLogger
151+
{
152+
public object BeginEvent(string eventName, string functionName = null, string data = null) => null;
153+
154+
public void BeginEvent(MetricEvent metricEvent)
155+
{
156+
}
157+
158+
public void EndEvent(MetricEvent metricEvent)
159+
{
160+
}
161+
162+
public void EndEvent(object eventHandle)
163+
{
164+
}
165+
166+
public void LogEvent(MetricEvent metricEvent)
167+
{
168+
}
169+
170+
public void LogEvent(string eventName, string functionName = null, string data = null)
171+
{
172+
}
173+
}
174+
146175
private class TestScriptHostBuilder : IScriptHostBuilder
147176
{
148177
private readonly DefaultScriptHostBuilder _builder;

test/WebJobs.Script.Tests/Configuration/ExpectedDependencyBuilderTests.cs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,67 @@ public void ExpectSingle_Factory()
5858
Assert.Empty(invalidDescriptors);
5959
}
6060

61+
[Fact]
62+
public void ExpectInstance()
63+
{
64+
ServiceCollection services = new ServiceCollection();
65+
services.AddSingleton<ITestSomething>(new TestSomethingA());
66+
services.AddSingleton<ITestSomething>(new TestSomethingB());
67+
68+
ExpectedDependencyBuilder validator = new ExpectedDependencyBuilder();
69+
validator.ExpectInstance<ITestSomething, TestSomethingB>();
70+
71+
var invalidDescriptors = validator.FindInvalidServices(services);
72+
Assert.Empty(invalidDescriptors);
73+
}
74+
75+
[Fact]
76+
public void ExpectInstance_Fail()
77+
{
78+
ServiceCollection services = new ServiceCollection();
79+
services.AddSingleton<ITestSomething>(new TestSomethingA());
80+
services.AddSingleton<ITestSomething>(new TestSomethingB());
81+
82+
ExpectedDependencyBuilder validator = new ExpectedDependencyBuilder();
83+
validator.ExpectInstance<ITestSomething, TestSomethingA>();
84+
85+
var invalidDescriptor = validator.FindInvalidServices(services).Single();
86+
Assert.Equal(typeof(ITestSomething), invalidDescriptor.Descriptor.ServiceType);
87+
Assert.Equal(typeof(TestSomethingB), invalidDescriptor.Descriptor.ImplementationInstance.GetType());
88+
}
89+
90+
[Fact]
91+
public void ExpectInstance_FailWithFactory()
92+
{
93+
ServiceCollection services = new ServiceCollection();
94+
services.AddSingleton<ITestSomething>(_ => new TestSomethingA());
95+
96+
ExpectedDependencyBuilder validator = new ExpectedDependencyBuilder();
97+
validator.ExpectInstance<ITestSomething, TestSomethingA>();
98+
99+
var invalidDescriptor = validator.FindInvalidServices(services).Single();
100+
Assert.Equal(typeof(ITestSomething), invalidDescriptor.Descriptor.ServiceType);
101+
Assert.Null(invalidDescriptor.Descriptor.ImplementationInstance);
102+
Assert.Null(invalidDescriptor.Descriptor.ImplementationType);
103+
Assert.NotNull(invalidDescriptor.Descriptor.ImplementationFactory);
104+
}
105+
106+
[Fact]
107+
public void ExpectInstance_FailWithReflection()
108+
{
109+
ServiceCollection services = new ServiceCollection();
110+
services.AddSingleton<ITestSomething, TestSomethingA>();
111+
112+
ExpectedDependencyBuilder validator = new ExpectedDependencyBuilder();
113+
validator.ExpectInstance<ITestSomething, TestSomethingA>();
114+
115+
var invalidDescriptor = validator.FindInvalidServices(services).Single();
116+
Assert.Equal(typeof(ITestSomething), invalidDescriptor.Descriptor.ServiceType);
117+
Assert.Null(invalidDescriptor.Descriptor.ImplementationInstance);
118+
Assert.Null(invalidDescriptor.Descriptor.ImplementationFactory);
119+
Assert.NotNull(invalidDescriptor.Descriptor.ImplementationType);
120+
}
121+
61122
[Fact]
62123
public void ExpectSingle_Type_Fail()
63124
{

0 commit comments

Comments
 (0)