2 public void CanCreateNewUser()
4 TestProvider.Initialize(ProviderName, DefaultConfig);
5 MembershipCreateStatus Status;
6 ApplicationUser UserToSave =
7 new ApplicationUser(CorrectUserName,
11 PasswordQuestion = ThePasswordQuestion,
12 PasswordAnswer = ThePasswordAnswer
14 UserRepository.Expect(x => x.Save(UserToSave))
17 MembershipUser NewUser =
25 out Status);
27 Assert.AreEqual(MembershipCreateStatus.Success, Status);
I hit run in my NUnit test runner and bam, I got this error
Tests.UnitTests.CustomMembershipProviderTestCase.CanCreateNewUser: System.ArgumentException : The membership provider name specified is invalid. Parameter name: providerName
At the top of the stack trace was the MembershipUser constructor so that's where I started my search. O how I love Reflector. I fired it up and examined the constructor for the MembershipUser class and spotted the following check
1 if ((providerName == null) ||
2 (Membership.Providers[providerName] == null))
4 throw new ArgumentException(
5 SR.GetString("Membership_provider_name_invalid"), "providerName");
There's the culprit : Membership.Providers[providerName] == null. So I tried setting the provider programmatically in my test, but the provider's collection is read only. I know that the provider's collection is populated according to what is in the web.config so I added the necessary section to the app.config of my test project.
2 <membership defaultProvider="CustomMembershipProvider">
4 <remove name="AspNetSqlMembershipProvider"/>
5 <add applicationName="UnitTests"
7 type="XXX.Infrastructure.Authentication.CustomMembershipProvider, XXX.Infrastructure"/>
I reran my test and I saw green, but I wasn't totally satisfied. The one thing I don't like about this solution is I can't control what's in the providers collection on a test by test basis.
In the back of my mind I knew I could use reflection, but I was avoiding it because I really wanted to move on. I quickly poked around the Membership and MembershipProvderCollection classes with reflector knowing, like many things, that somebody has probably solved this problem. Within minutes I found Colin Bowern's post describing the same exact issue. The code below to programmatically populate the provider's collection is to his credit. Thanks Colin.
1 private void InjectProvider(ProviderCollection Collection, ProviderBase Provider)
3 typeof(ProviderCollection).GetField("_ReadOnly", BindingFlags.Instance | BindingFlags.NonPublic)
4 .SetValue(Collection, false);
6 Hashtable Hash = (Hashtable)typeof(ProviderCollection).GetField("_Hashtable", BindingFlags.Instance | BindingFlags.NonPublic)
9 if (Hash[Provider.Name] == null)
11 Hash.Add(Provider.Name, Provider);
15 Hash[Provider.Name] = Provider;
Now the top two lines of my test look like
1 TestProvider.Initialize(ProviderName, DefaultConfig);
2 InjectProvider(Membership.Providers, TestProvider);
And my test still passes.