Skip to content

Commit 7eea654

Browse files
committed
Merge branch 'release/3.7.0'
2 parents 03b3e64 + 9f80d02 commit 7eea654

103 files changed

Lines changed: 579 additions & 97 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/Patterns.Testing/App.config

Lines changed: 0 additions & 9 deletions
This file was deleted.
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
#region FreeBSD
2+
3+
// Copyright (c) 2013, John Batte
4+
// All rights reserved.
5+
//
6+
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
7+
//
8+
// * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
9+
//
10+
// * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
11+
// documentation and/or other materials provided with the distribution.
12+
//
13+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
14+
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
15+
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
16+
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
17+
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
18+
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19+
20+
#endregion
21+
22+
using System;
23+
using System.Collections.Generic;
24+
using System.Configuration;
25+
using System.Linq;
26+
using System.Reflection;
27+
using System.Xml.Linq;
28+
29+
using Patterns.Configuration;
30+
31+
namespace Patterns.Testing.Configuration
32+
{
33+
/// <summary>
34+
/// Provides a configuration source that uses an in-memory configuration rather than a
35+
/// file-based one.
36+
/// </summary>
37+
public class TestConfigurationSource : IConfigurationSource
38+
{
39+
private readonly XContainer _configXml;
40+
41+
/// <summary>
42+
/// Initializes a new instance of the <see cref="TestConfigurationSource" /> class.
43+
/// </summary>
44+
/// <param name="configXml">The config XML.</param>
45+
public TestConfigurationSource(XContainer configXml)
46+
{
47+
_configXml = configXml;
48+
var appSettings = GetSection<AppSettingsSection>("appSettings");
49+
if (appSettings != null)
50+
{
51+
AppSettings = appSettings.Settings.AllKeys
52+
.ToDictionary(key => key, key => appSettings.Settings[key].Value);
53+
}
54+
var connectionStrings = GetSection<ConnectionStringsSection>("connectionStrings");
55+
if (connectionStrings != null)
56+
{
57+
ConnectionStrings = connectionStrings.ConnectionStrings.OfType<ConnectionStringSettings>()
58+
.ToDictionary(settings => settings.Name, settings => settings);
59+
}
60+
}
61+
62+
/// <summary>
63+
/// Gets the app settings.
64+
/// </summary>
65+
/// <value>
66+
/// The app settings.
67+
/// </value>
68+
public IDictionary<string, string> AppSettings { get; private set; }
69+
70+
/// <summary>
71+
/// Gets the connection strings.
72+
/// </summary>
73+
/// <value>
74+
/// The connection strings.
75+
/// </value>
76+
public IDictionary<string, ConnectionStringSettings> ConnectionStrings { get; private set; }
77+
78+
/// <summary>
79+
/// Gets the section.
80+
/// </summary>
81+
/// <param name="sectionName">Name of the section.</param>
82+
/// <returns></returns>
83+
/// <exception cref="System.NotImplementedException"></exception>
84+
public ConfigurationSection GetSection(string sectionName)
85+
{
86+
return DeserializeSection(_configXml, sectionName);
87+
}
88+
89+
/// <summary>
90+
/// Gets the section.
91+
/// </summary>
92+
/// <typeparam name="TSection">The type of the section.</typeparam>
93+
/// <param name="sectionName">Name of the section.</param>
94+
/// <returns></returns>
95+
/// <exception cref="System.NotImplementedException"></exception>
96+
public TSection GetSection<TSection>(string sectionName) where TSection : ConfigurationSection, new()
97+
{
98+
return DeserializeSection<TSection>(_configXml, sectionName);
99+
}
100+
101+
/// <summary>
102+
/// Opens the exe configuration.
103+
/// </summary>
104+
/// <param name="exePath">The exe path.</param>
105+
/// <returns></returns>
106+
/// <exception cref="System.NotImplementedException"></exception>
107+
public IConfiguration OpenExeConfiguration(string exePath)
108+
{
109+
throw new NotSupportedException();
110+
}
111+
112+
/// <summary>
113+
/// Opens the machine configuration.
114+
/// </summary>
115+
/// <returns></returns>
116+
/// <exception cref="System.NotImplementedException"></exception>
117+
public IConfiguration OpenMachineConfiguration()
118+
{
119+
throw new NotSupportedException();
120+
}
121+
122+
/// <summary>
123+
/// Refreshes the section.
124+
/// </summary>
125+
/// <param name="sectionName">Name of the section.</param>
126+
/// <exception cref="System.NotImplementedException"></exception>
127+
public void RefreshSection(string sectionName) {}
128+
129+
/// <summary>
130+
/// Opens the mapped exe configuration.
131+
/// </summary>
132+
/// <param name="fileMap">The file map.</param>
133+
/// <param name="userLevel">The user level.</param>
134+
/// <returns></returns>
135+
/// <exception cref="System.NotImplementedException"></exception>
136+
public IConfiguration OpenMappedExeConfiguration(ExeConfigurationFileMap fileMap, ConfigurationUserLevel userLevel)
137+
{
138+
throw new NotSupportedException();
139+
}
140+
141+
/// <summary>
142+
/// Opens the exe configuration.
143+
/// </summary>
144+
/// <param name="userLevel">The user level.</param>
145+
/// <returns></returns>
146+
/// <exception cref="System.NotImplementedException"></exception>
147+
public IConfiguration OpenExeConfiguration(ConfigurationUserLevel userLevel)
148+
{
149+
throw new NotSupportedException();
150+
}
151+
152+
private static ConfigurationSection DeserializeSection(XContainer xml, string name)
153+
{
154+
XElement sectionDefinition = xml.Element("configSections")
155+
.Elements("section")
156+
.FirstOrDefault(section => section.Attribute("name").Value == name);
157+
158+
if (sectionDefinition == null) return null;
159+
160+
Type sectionType = Type.GetType(sectionDefinition.Attribute("type").Value, false);
161+
162+
if (sectionType == null) return null;
163+
164+
const BindingFlags flags = BindingFlags.Static | BindingFlags.NonPublic;
165+
MethodInfo genericFlavor = typeof (TestConfigurationSource).GetMethods(flags)
166+
.FirstOrDefault(method => method.Name == "DeserializeSection" && method.IsGenericMethod);
167+
168+
MethodInfo typedGenericFlavor = genericFlavor.MakeGenericMethod(sectionType);
169+
170+
try
171+
{
172+
return (ConfigurationSection) typedGenericFlavor.Invoke(null, new object[] {xml, name});
173+
}
174+
catch (TargetInvocationException error)
175+
{
176+
throw error.InnerException;
177+
}
178+
}
179+
180+
private static TSection DeserializeSection<TSection>(XContainer xml, string name) where TSection : ConfigurationSection, new()
181+
{
182+
var config = new TSection();
183+
const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
184+
MethodInfo deserializer = typeof (TSection).GetMethod("DeserializeSection", flags);
185+
XElement sectionXml = xml.Element(name);
186+
if (sectionXml == null) return null;
187+
188+
try
189+
{
190+
deserializer.Invoke(config, new object[] {sectionXml.CreateReader()});
191+
}
192+
catch (TargetInvocationException error)
193+
{
194+
throw error.InnerException;
195+
}
196+
197+
return config;
198+
}
199+
}
200+
}

src/Patterns.Testing/Moq/MoqContainer.cs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,22 +37,51 @@ namespace Patterns.Testing.Moq
3737
/// </summary>
3838
public sealed class MoqContainer : AccessibleContainer, IMoqContainer
3939
{
40+
/// <summary>
41+
/// Initializes a new instance of the <see cref="MoqContainer" /> class.
42+
/// </summary>
43+
/// <param name="container">The container.</param>
4044
public MoqContainer(IContainer container) : base(container)
4145
{
4246
Locator = new AutofacServiceLocator(this);
4347
ComponentRegistry.AddRegistrationSource(new MoqRegistrationSource());
4448
}
4549

50+
/// <summary>
51+
/// Initializes a new instance of the <see cref="MoqContainer" /> class.
52+
/// </summary>
4653
public MoqContainer() : this(new ContainerBuilder().Build()) {}
4754

55+
/// <summary>
56+
/// Gets the locator.
57+
/// </summary>
58+
/// <value>
59+
/// The locator.
60+
/// </value>
4861
public IServiceLocator Locator { get; private set; }
4962

63+
/// <summary>
64+
/// Retrieves the mock for the specified service type.
65+
/// </summary>
66+
/// <typeparam name="TService">The type of the service.</typeparam>
67+
/// <returns>
68+
/// The service mock.
69+
/// </returns>
5070
public Mock<TService> Mock<TService>() where TService : class
5171
{
5272
var obj = (IMocked<TService>) Create<TService>();
5373
return obj.Mock;
5474
}
5575

76+
/// <summary>
77+
/// Creates an instance of the specified service, injecting mocked objects
78+
/// for all unregistered dependencies.
79+
/// </summary>
80+
/// <typeparam name="TService">The type of the service.</typeparam>
81+
/// <param name="activator">The optional activator.</param>
82+
/// <returns>
83+
/// The service instance.
84+
/// </returns>
5685
public TService Create<TService>(Func<IMoqContainer, TService> activator = null) where TService : class
5786
{
5887
Action<ContainerBuilder> defaultRegistration = builder => builder.RegisterType<TService>()
@@ -64,6 +93,14 @@ public TService Create<TService>(Func<IMoqContainer, TService> activator = null)
6493
return ResolveOrCreate<TService>(activator == null ? defaultRegistration : activatorRegistration);
6594
}
6695

96+
/// <summary>
97+
/// Updates this instance by registering the implementation type as the service type.
98+
/// </summary>
99+
/// <typeparam name="TService">The type of the service.</typeparam>
100+
/// <typeparam name="TImplementation">The type of the implementation.</typeparam>
101+
/// <returns>
102+
/// The container.
103+
/// </returns>
67104
public IMoqContainer Update<TService, TImplementation>() where TService : class where TImplementation : TService
68105
{
69106
Update(builder => builder.RegisterType<TImplementation>().As<TService>()
@@ -72,6 +109,14 @@ public IMoqContainer Update<TService, TImplementation>() where TService : class
72109
return this;
73110
}
74111

112+
/// <summary>
113+
/// Updates this instance by registering an instance of the specified service.
114+
/// </summary>
115+
/// <typeparam name="TService">The type of the service.</typeparam>
116+
/// <param name="instance">The instance.</param>
117+
/// <returns>
118+
/// The container.
119+
/// </returns>
75120
public IMoqContainer Update<TService>(TService instance) where TService : class
76121
{
77122
Update(builder => builder.RegisterInstance(instance).As<TService>()
@@ -80,9 +125,18 @@ public IMoqContainer Update<TService>(TService instance) where TService : class
80125
return this;
81126
}
82127

128+
/// <summary>
129+
/// Updates this instance by registering the specified activator as the service type.
130+
/// </summary>
131+
/// <typeparam name="TService">The type of the service.</typeparam>
132+
/// <param name="activator">The activator.</param>
133+
/// <returns>
134+
/// The container
135+
/// </returns>
83136
public IMoqContainer Update<TService>(Func<IMoqContainer, TService> activator) where TService : class
84137
{
85-
Update(builder => builder.Register<TService>(c => activator(this)).As<TService>().PropertiesAutowired(PropertyWiringOptions.PreserveSetValues));
138+
Update(builder => builder.Register(c => activator(this)).As<TService>()
139+
.PropertiesAutowired(PropertyWiringOptions.PreserveSetValues));
86140

87141
return this;
88142
}

src/Patterns.Testing/Moq/MoqRegistrationSource.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,33 @@
1010

1111
namespace Patterns.Testing.Moq
1212
{
13+
/// <summary>
14+
/// Provides a registration source for Autofac using Moq's MockRepository as a service factory.
15+
/// </summary>
1316
public class MoqRegistrationSource : IRegistrationSource
1417
{
1518
private static readonly MockRepository _repository = new MockRepository(MockBehavior.Default);
1619
private static readonly MethodInfo _createMethod = typeof(MoqRegistrationSource)
1720
.GetMethod("CreateUsingRepository", BindingFlags.NonPublic | BindingFlags.Instance)
1821
.GetGenericMethodDefinition();
1922

23+
/// <summary>
24+
/// Retrieve registrations for an unregistered service, to be used
25+
/// by the container.
26+
/// </summary>
27+
/// <param name="service">The service that was requested.</param>
28+
/// <param name="registrationAccessor">A function that will return existing registrations for a service.</param>
29+
/// <returns>
30+
/// Registrations providing the service.
31+
/// </returns>
32+
/// <exception cref="System.ArgumentNullException">service</exception>
33+
/// <remarks>
34+
/// If the source is queried for service s, and it returns a component that implements both s and s', then it
35+
/// will not be queried again for either s or s'. This means that if the source can return other implementations
36+
/// of s', it should return these, plus the transitive closure of other components implementing their
37+
/// additional services, along with the implementation of s. It is not an error to return components
38+
/// that do not implement <paramref name="service" />.
39+
/// </remarks>
2040
public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
2141
{
2242
if (service == null) throw new ArgumentNullException("service");
@@ -42,6 +62,10 @@ public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Fun
4262
};
4363
}
4464

65+
/// <summary>
66+
/// Gets whether the registrations provided by this source are 1:1 adapters on top
67+
/// of other components (I.e. like Meta, Func or Owned.)
68+
/// </summary>
4569
public bool IsAdapterForIndividualComponents
4670
{
4771
get { return false; }

src/Patterns.Testing/Patterns.Testing.csproj

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,20 +54,19 @@
5454
<HintPath>..\packages\Moq.4.0.10827\lib\NET40\Moq.dll</HintPath>
5555
</Reference>
5656
<Reference Include="System" />
57+
<Reference Include="System.Configuration" />
5758
<Reference Include="System.Core" />
5859
<Reference Include="System.Xml.Linq" />
5960
<Reference Include="System.Data.DataSetExtensions" />
6061
<Reference Include="Microsoft.CSharp" />
6162
<Reference Include="System.Data" />
6263
<Reference Include="System.Xml" />
63-
<Reference Include="TechTalk.SpecFlow">
64-
<HintPath>..\packages\SpecFlow.1.9.0\lib\net35\TechTalk.SpecFlow.dll</HintPath>
65-
</Reference>
6664
</ItemGroup>
6765
<ItemGroup>
6866
<Compile Include="..\Patterns\SolutionAssemblyInfo.cs">
6967
<Link>Properties\SolutionAssemblyInfo.cs</Link>
7068
</Compile>
69+
<Compile Include="Configuration\TestConfigurationSource.cs" />
7170
<Compile Include="Moq\IMoqContainer.cs" />
7271
<Compile Include="Moq\MoqContainer.cs" />
7372
<Compile Include="Moq\MoqRegistrationSource.cs" />
@@ -85,7 +84,6 @@
8584
</ProjectReference>
8685
</ItemGroup>
8786
<ItemGroup>
88-
<None Include="App.config" />
8987
<None Include="packages.config" />
9088
<None Include="Patterns.Testing.nuspec">
9189
<AutoGen>True</AutoGen>

src/Patterns.Testing/packages.config

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,4 @@
55
<package id="AutoMapper" version="2.2.1" targetFramework="net40" />
66
<package id="CommonServiceLocator" version="1.0" targetFramework="net40" />
77
<package id="Moq" version="4.0.10827" targetFramework="net40" />
8-
<package id="SpecFlow" version="1.9.0" targetFramework="net40" />
98
</packages>

0 commit comments

Comments
 (0)