forked from autofac/Autofac
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CircularDependencyDetectorTests.cs
168 lines (144 loc) · 5.38 KB
/
CircularDependencyDetectorTests.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Autofac.Core;
using Autofac.Core.Resolving;
using Xunit;
namespace Autofac.Test.Core.Resolving
{
public class CircularDependencyDetectorTests
{
[Fact]
public void OnCircularDependency_MessageDescribesCycle()
{
var builder = new ContainerBuilder();
builder.Register(c => c.Resolve<object>());
var target = builder.Build();
var de = Assert.Throws<DependencyResolutionException>(() => target.Resolve<object>());
Assert.Contains("System.Object -> System.Object", de.Message);
Assert.DoesNotContain("System.Object -> System.Object -> System.Object", de.Message);
}
[Fact]
public void MaxStackDepthExceeded_ThrowsCircularDependencyException()
{
var builder = new ContainerBuilder().WithMaxResolveStackDepth(10);
builder.RegisterType<OuterScopeType>();
builder.RegisterType<OuterScopeType2>();
builder.RegisterType<OuterScopeType3>();
builder.RegisterType<OuterScopeType4>();
builder.RegisterType<OuterScopeType5>();
IContainer container = builder.Build();
using (var lifetimeScope = container.BeginLifetimeScope(b => b.RegisterType<InnerScopeType>()))
{
Assert.Throws<DependencyResolutionException>(() => lifetimeScope.Resolve<InnerScopeType>());
}
}
[Fact]
public void MaxStackDepthNotExceeded_CanBeResolved()
{
var builder = new ContainerBuilder().WithMaxResolveStackDepth(11);
builder.RegisterType<OuterScopeType>();
builder.RegisterType<OuterScopeType2>();
builder.RegisterType<OuterScopeType3>();
builder.RegisterType<OuterScopeType4>();
builder.RegisterType<OuterScopeType5>();
IContainer container = builder.Build();
using (var lifetimeScope = container.BeginLifetimeScope(b => b.RegisterType<InnerScopeType>()))
{
Assert.NotNull(lifetimeScope.Resolve<InnerScopeType>());
}
}
[Fact(Skip = "Issue #648")]
public void ManualEnumerableRegistrationDoesNotCauseCircularDependency()
{
var builder = new ContainerBuilder();
builder.RegisterType<RootViewModel>().AsSelf().SingleInstance();
builder.RegisterType<PluginsViewModel>().AsSelf().SingleInstance();
builder.RegisterType(typeof(Plugin1)).Named<IPlugin>("Plugin1");
builder.RegisterType(typeof(Plugin2)).Named<IPlugin>("Plugin2");
builder.Register(
ctx => new[] { "Plugin1", "Plugin2" }
.Select(name => SafeResolvePlugin(name, ctx))
.Where(p => p != null)
.ToArray())
.As<IEnumerable<IPlugin>>()
.SingleInstance();
var container = builder.Build();
// From issue 648, this resolve call was getting a circular dependency
// detection exception. It shouldn't be getting anything because the "safe resolve"
// eats the dependency resolution issue for Plugin2 and Plugin1 should be
// properly resolved.
Assert.NotNull(container.Resolve<RootViewModel>());
Assert.Single(container.Resolve<IEnumerable<IPlugin>>());
}
private static IPlugin SafeResolvePlugin(string pluginName, IComponentContext core)
{
try
{
// Plugin2 will get filtered out because it has an
// unavailable dependency.
return core.ResolveNamed<IPlugin>(pluginName);
}
catch (DependencyResolutionException)
{
return null;
}
}
private interface IPlugin
{
}
private class Plugin1 : IPlugin
{
}
private class Plugin2 : IPlugin
{
public Plugin2(IUnavailableComponent unavailableComponent)
{
}
}
private interface IUnavailableComponent
{
}
private class PluginsViewModel
{
public PluginsViewModel(IEnumerable<IPlugin> plugins)
{
}
}
private class RootViewModel
{
public RootViewModel(IEnumerable<IPlugin> plugins, PluginsViewModel pluginsViewModel)
{
}
}
public class OuterScopeType
{
public OuterScopeType(OuterScopeType2 outerScopeType2) { }
}
public class OuterScopeType2
{
public OuterScopeType2(OuterScopeType3 outerScopeType3) { }
}
public class OuterScopeType3
{
public OuterScopeType3(OuterScopeType4 outerScopeType4) { }
}
public class OuterScopeType4
{
public OuterScopeType4(OuterScopeType5 outerScopeType5) { }
}
public class OuterScopeType5 { }
public class InnerScopeType
{
public InnerScopeType(
OuterScopeType outerScopeType,
OuterScopeType4 outerScopeType4,
OuterScopeType5 outerScopeType5
)
{
}
}
}
}