 |
Telerik OpenAccess ORM Q1 2010 Release comes with several new or renamed assemblies:
- Telerik.OpenAccess.Query.dll is renamed to Telerik.OpenAccess.35.Extensions.dll
- Telerik.OpenAccess.40.dll is renamed to Telerik.OpenAcces.40.Extensions.dll
- There is separation of the Win and Web UI into separate assemblies out of Telerik.OpenAccess.dll. These are Telerik.OpenAccess.Web.dll and Telerik.OpenAccess.Windows.dll assemblies.
|
While using an unit test framework, such as NUnit or the one from the Visual Studio Test tools, the most common mistake is a wrong config file setting. The root cause of this generally is that the config file used is the one from the test driver (nunit-gui.exe, UnitTestRunner) not the one specified in the user assembly. This can be easily avoided using the following settings:
For NUnit
To hold the test code, use a library assembly.
Enable the project for OpenAccess ORM (using the Enable Project Wizard) and generate the helper class, i.e. ObjectScopeProvider for connected database access.
Use the generated ObjectScopeProvider to obtain IObjectScope instances.
The App.config file must have the "Build Action" property set to "Embedded Resource", i.e., the configuration files are added as embedded resources.
The starting assembly is the test driver of NUnit, e.g. "C:\Program Files\NUnit-Net-2.0 2.2.8\bin\nunit-gui.exe". Pass the project file (<LibraryName>.csproj) as a parameter.
For Microsoft.VisualStudio.TestTools.UnitTesting
Generate a project of type "Test Project".
Enable the project for OpenAccess ORM (using the Enable Project Wizard) and generate the helper class, i.e. ObjectScopeProvider for connected database access.
Use the generated ObjectScopeProvider to obtain IObjectScope instances.
The App.config file must have the "Build Action" property set to "Embedded Resource", i.e., the configuration files are added as embedded resources.
CodeCoverage testing will not work. The reason is that the embedded resources do not get copied over correctly by the test framework tools.
While using multiple assemblies to hold test code and persistent classes, problems arising from wrong configuration can be avoided by using the configrequired attribute in the App.config file of the test code assembly as shown below:
| App.config |
Copy Code |
<openaccess xmlns="http://www.Telerik.com/OpenAccess">
<references>
<reference assemblyname="MyPersistentModel" configrequired="true"/>
</references>
</openaccess>
|
This will force the runtime to throw an exception if the App.config file (either as embedded resource or as file) of the assembly is not present at database open time.
A sample approach to testing will be introduced in the following content. MS Test Framework is used.
Create a base transactional test class
We will encapsulate all the object scope, connection settings and transactional logic iside the base class.
| C# |
Copy Code |
|
using System; using System.Collections.Generic; using System.Text; using Microsoft.VisualStudio.TestTools.UnitTesting; using System.IO; using System.Data.SqlClient; using OpenAccessNorthwindMapping; using Telerik.OpenAccess; using Telerik.OpenAccess.Query; namespace TestProject1 { /// <summary> /// Summary description for UnitTest1 /// </summary> [TestClass] public class TestBase { public TestBase() { // // TODO: Add constructor logic here // } private static TestContext testContextInstance; protected IObjectScope scope; /// <summary> ///Gets or sets the test context which provides ///information about and functionality for the current test run. ///</summary> public TestContext TestContext { get { return testContextInstance; } set { testContextInstance = value; } } //Use ClassInitialize to run code before running the first test in the class [ClassInitialize()] public static void TestBaseInitialize(TestContext testContext) { OpenAccessNorthwindMapping.ObjectScopeProvider1.AdjustForDynamicLoad(); } //Use ClassCleanup to run code after all tests in a class have run [ClassCleanup()] public static void LastTestBaseCleanup() { testContextInstance = null; } //Use TestInitialize to run code before running each test [TestInitialize()] public void TestBaseInitialize() { // we prepare the OpenAccess model here scope = OpenAccessNorthwindMapping.ObjectScopeProvider1.GetNewObjectScope(); scope.Transaction.Begin(); } //Use TestCleanup to run code after each test has run [TestCleanup()] public void TestBaseCleanup() { if (scope.Transaction.IsActive) { scope.Transaction.Rollback(); } scope.Dispose(); } } } |
| VB.NET |
Copy Code |
|
Imports System Imports System.Collections.Generic Imports System.Text Imports Microsoft.VisualStudio.TestTools.UnitTesting Imports System.IO Imports System.Data.SqlClient Imports OpenAccessNorthwindMapping Imports Telerik.OpenAccess Imports Telerik.OpenAccess.Query Namespace TestProject1 <TestClass> _ Public Class TestBase Public Sub New() End Sub Private Shared testContextInstance As TestContext Protected scope As IObjectScope Public Property TestContext() As TestContext Get Return testContextInstance End Get Set(ByVal value As TestContext) testContextInstance = value End Set End Property <ClassInitialize()> _ Public Shared Sub TestBaseInitialize(ByVal testContext As TestContext) OpenAccessNorthwindMapping.ObjectScopeProvider1.AdjustForDynamicLoad() End Sub <ClassCleanup()> _ Public Shared Sub LastTestBaseCleanup() testContextInstance = Nothing End Sub <TestInitialize()> _ Public Sub TestBaseInitialize() scope = OpenAccessNorthwindMapping.ObjectScopeProvider1.GetNewObjectScope() scope.Transaction.Begin() End Sub <TestCleanup()> _ Public Sub TestBaseCleanup() If scope.Transaction.IsActive Then scope.Transaction.Rollback() End If scope.Dispose() End Sub End Class End Namespace |
Create concrete test class with unit tests
Having the base class now we can prepare the real test container:
| C# |
Copy Code |
|
using System; using System.Text; using System.Collections.Generic; using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; using NorthwindMapping; using OpenAccessNorthwindMapping; using Telerik.OpenAccess; using Telerik.OpenAccess.Query; using System.Linq.Expressions; namespace TestProject1 { /// <summary> /// Summary description for Advanced /// </summary> [TestClass] public class AdvancedTest : TestBase { public AdvancedTest() { // // TODO: Add constructor logic here // } #region Additional test attributes [ClassInitialize()] public static void MyClassInitialize(TestContext testContext) { TestBase.TestBaseInitialize(testContext); } //Use ClassCleanup to run code after all tests in a class have run [ClassCleanup()] public static void LastTestBaseCleanup() { TestBase.LastTestBaseCleanup(); } #endregion [TestMethod] public void DynamicQuerySelect() { //linq to OpenAccess: } } } |
| VB.NET |
Copy Code |
|
Imports System Imports System.Text Imports System.Collections.Generic Imports System.Linq Imports Microsoft.VisualStudio.TestTools.UnitTesting Imports NorthwindMapping Imports OpenAccessNorthwindMapping Imports Telerik.OpenAccess Imports Telerik.OpenAccess.Query Imports System.Linq.Expressions Namespace TestProject1 <TestClass> _ Public Class AdvancedTest Inherits TestBase Public Sub New() End Sub #Region "Additional test attributes" <ClassInitialize()> _ Public Shared Sub MyClassInitialize(ByVal testContext As TestContext) TestBase.TestBaseInitialize(testContext) End Sub <ClassCleanup()> _ Public Shared Sub LastTestBaseCleanup() TestBase.LastTestBaseCleanup() End Sub #End Region <TestMethod> _ Public Sub DynamicQuerySelect() End Sub End Class End Namespace |
Writing a unit test
Now we can write the unit test:
| C# |
Copy Code |
|
[TestMethod] public void DynamicQuerySelect() { // here we populate the results we test against List<string> linqResult = GetCompares(); //linq to OpenAccess: ParameterExpression oaParam = Expression.Parameter(typeof(CustomerOA), "c"); Expression oaSelector = Expression.Property(oaParam, typeof(CustomerOA).GetProperty("ContactName")); var oaPred = Expression.Lambda(oaSelector, oaParam); var oaCusts = scope.Extent<CustomerOA>(); var oaExpr = Expression.Call(typeof(Queryable), "Select", new Type[] { typeof(CustomerOA), typeof(string) }, Expression.Constant(oaCusts), oaPred); var oaQuery = scope.Extent<CustomerOA>().AsQueryable().Provider.CreateQuery<string>(oaExpr); List<string> oaResult = oaQuery.ToList(); Assert.AreEqual(linqResult.Count(), oaResult.Count()); for (int i = 0; i < linqResult.Count; i++) { Assert.AreEqual(linqResult[i], oaResult[i]); base.TestContext.WriteLine("{0} - {1}", linqResult[i], oaResult[i]); } } |
| VB.NET |
Copy Code |
|
<TestMethod> _ Public Sub DynamicQuerySelect() Dim linqResult As List(Of String) = GetCompares() Dim oaParam As ParameterExpression = Expression.Parameter(GetType(CustomerOA), "c") Dim oaSelector As Expression = Expression.Property(oaParam, GetType(CustomerOA).GetProperty("ContactName")) Dim oaPred = Expression.Lambda(oaSelector, oaParam) Dim oaCusts = scope.Extent(Of CustomerOA)() Dim oaExpr = Expression.Call(GetType(Queryable), "Select", New Type() { GetType(CustomerOA), GetType(String) }, Expression.Constant(oaCusts), oaPred) Dim oaQuery = scope.Extent(Of CustomerOA)().AsQueryable().Provider.CreateQuery(Of String)(oaExpr) Dim oaResult As List(Of String) = oaQuery.ToList() Assert.AreEqual(linqResult.Count(), oaResult.Count()) For i As Integer = 0 To linqResult.Count - 1 Assert.AreEqual(linqResult(i), oaResult(i)) MyBase.TestContext.WriteLine("{0} - {1}", linqResult(i), oaResult(i)) Next i End Sub |