Unit Testing an Application with a DAL Generated by SubSonic
I am currently working on an inherited codebase. One of the critical missing pieces is unit testing. I seem to have run into a roadblock while trying to set up some unit tests in NUnit.
I created a separate unit testing project as normal, added the necessary references to SubSonic, NUnit and the various DLLs created by the application and set up a dummy unit test to ensure everything is set up correctly. The problems started when I attempted to re开发者_如何学Goference some of the objects generated by SubSonic. I created this test to list users:
[Test]
public void CanListUsers()
{
UserCollection users = UserController.List(UserController
.Query()
.Where(User.Columns.IsDeleted, false));
Assert.IsNotNull(users);
}
and got this exception:
Can't find the SubSonicService in your application's config
I fixed that by pulling out the parts of the Web.config that were related to SubSonic into an App.config in the unit testing project. Now, when I rerun the unit tests, I get:
UnitTests.TestClass.CanListUsers: System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation. ----> System.Configuration.ConfigurationErrorsException : Could not load type 'Utility.SqlSubsonicProvider' from assembly 'System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
This exception has me confused because SqlSubsonicProvider is a class in the Utility namespace and can be seen in Object Browser so why is it being looked for in System.Web?
Edit: Okay, I have rearranged the namespaces in the solution so that they make more sense. I think that fixed the above error. Unfortunately I'm now getting this error:
ChannelMechanics.UnitTests.TestClass.CanListVendors:
System.Reflection.TargetInvocationException : Exception has been thrown by the target
of an invocation.
----> System.NullReferenceException : Object reference not set to an instance of
an object.
What's even stranger is that the unit test passes when I use Visual Studio's "Attach to Process" command in the Debug menu and attach to the NUnit GUI. My theory was that the null object would be easily spotted from within the debugger.
If it helps, my App.config looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="SubSonicService"
type="SubSonic.SubSonicSection, SubSonic"
requirePermission="false"/>
</configSections>
<connectionStrings>
<add name="DatabaseConnection"
connectionString="*removed*"/>
</connectionStrings>
<SubSonicService defaultProvider="TestProvider">
<providers>
<clear />
<add name="TestProvider"
type="SubSonic.SqlDataProvider, SubSonic"
connectionStringName="DatabaseConnection"
generatedNamespace="Test"/>
</providers>
</SubSonicService>
</configuration>
The exception details are:
at System.RuntimeTypeHandle.CreateInstance(RuntimeType type,
Boolean publicOnly, Boolean noCheck, Boolean& canBeCached,
RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis,
Boolean fillCache)
at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly,
Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache)
at System.Activator.CreateInstance[T]()
at SubSonic.ActiveController`2.Query()
at UnitTests.TestClass.CanListVendors() in UnitTests\TestClass.cs:line 59
--NullReferenceException
at DataAccess.Vendor.GetTableSchema() in DataAccess\Generated\Models\Vendor.cs:line 376
at DataAccess.Vendor.SetSQLProps() in DataAccess\Generated\Models\Vendor.cs:line 42
at DataAccess.Vendor..ctor() in DataAccess\Generated\Models\Vendor.cs:line 35
The test that I am running is basically the same as the one listed above except it's Vendors rather than Users that should be getting listed.
[Test]
public void CanListVendors()
{
VendorCollection vendors = VendorController.List(
VendorController
.Query()
.Where(Vendor.Columns.IsDeleted, false));
Assert.IsNotNull(vendors);
}
I would suggest there is a System.Web.Utility
namespace, and you get this wrong error message because the compiler "thinks" he has to look inside this namespace for resolving the class.
Please check that your test project is set to target framework "Framework 4" and not "Framework 4 Client Profile".
Missing ".NET Framework 4 Client Profile" as target framework in "New Project" window
This seems to be working now. The only change I made within the project was to create a separate test project using Visual Studio's unit test capabilities. The only other explanation I can think of is that something troublesome got thrown out of memory when I rebooted the computer between yesterday evening and today.
For the benefit of anyone stumbling on this question in the future, here is a summary of the steps I took to get NUnit testing a DAL generated by SubSonic:
- Create new class library project.
- Add necessary references - I added the DAL, NUnit and SubSonic.
- Add an App.config file so that SubSonic knows where to find the SubSonic service. All I did for this was to pull out the parts in Web.config that were related to SubSonic.
- Add a test class and start adding tests to it.
If your tests are inexplicably failing, make sure the "Copy to Output Directory" is set to "Copy if newer" for the App.config that was added, make sure the provider name in App.config matches the provider name used in the DAL classes and, if all else fails, reboot!
Do you always have SubSonic not Subsonic?
This is the relevant section from my nunit projects config file which works...
<configSections>
<section name="SubSonicService"
type="SubSonic.SubSonicSection, SubSonic"
requirePermission="false"/>
</configSections>
<SubSonicService defaultProvider="TAProvider">
<providers>
<clear />
<add name="TAProvider"
type="SubSonic.SqlDataProvider, SubSonic"
connectionStringName="TATesting"
generatedNamespace="DALTA"/>
</providers>
</SubSonicService>
精彩评论