Hello!
I have troubles with getting my test case to work, possibly due to a lack of understanding of the principles to set this up correctly.
Environment: Entity Framework and .NET 4, Visual Studio 2010, MS SQL Server 2008
What I would like to do, is to test a short method "TryToGetObject", which is defined in BaseClass<T>.
The method takes an object named "importObject" of type "SomeEntityType".
The method passes this object to the compiled query and uses the property "ItemId" of it to find the matching data in the Entity Framework ObjectContext (if it exists).
For this test I wanted to mock the ObjectContext, so that I can avoid a real database access.
Here is my setup (Code is provided below):
Can anyone please provide me some guidance what I am doing wrong?
Thank you in advance and best wishes,
Jens
BaseClass<T>
DerivedClass<SomeEntityType>
The test class:
I have troubles with getting my test case to work, possibly due to a lack of understanding of the principles to set this up correctly.
Environment: Entity Framework and .NET 4, Visual Studio 2010, MS SQL Server 2008
What I would like to do, is to test a short method "TryToGetObject", which is defined in BaseClass<T>.
The method takes an object named "importObject" of type "SomeEntityType".
The method passes this object to the compiled query and uses the property "ItemId" of it to find the matching data in the Entity Framework ObjectContext (if it exists).
For this test I wanted to mock the ObjectContext, so that I can avoid a real database access.
Here is my setup (Code is provided below):
- SomeObjectContext: The Entity Framework context that provides access to the database
- SomeEntityType: The type that represents the data of a table in the database
- Class Baseclass<T>: Provides the pasic functionality for all derived classes.
- DerivedClass<SomeEntityType>: Derives from BaseClass<T> and overrides property "CompiledQueryGetObject" to provide the specific implementation of the compiled query.
- UnitTest1.TestMethod1() shows various attempty to mock the acces to the query, all of which do not work. The comments above them show the particular error message.
Can anyone please provide me some guidance what I am doing wrong?
Thank you in advance and best wishes,
Jens
BaseClass<T>
namespace MyNamespace
{
/// <
summary
>
/// Provides methods to access a database table.
/// </
summary
>
public abstract class BaseClass<
T
> where T : EntityObject
{
#region Properties
/// <
summary
>
/// Is overriden in derived classes.
/// </
summary
>
protected abstract Func<
SomeObjectContext
, T, T> CompiledQueryGetObject { get; }
/// <
summary
>
/// Context for database operations (EntityFramework)
/// </
summary
>
protected SomeObjectContext Context { get; set; }
#endregion Properties
#region Constructors
/// <
summary
>
/// Creates a new instance of type BaseClass.
/// </
summary
>
/// <
param
name
=
"context"
>The current database context.</
param
>
public BaseClass(SomeObjectContext context)
{
this.Context = context;
}
#endregion Constructors
#region Public methods
/// <
summary
>
/// Tries to retrieve the given object from the database by its unique database constraints.
/// </
summary
>
/// <
param
name
=
"importObject"
>Given entity object.</
param
>
/// <
returns
>Object if found, otherwise null</
returns
>
public T TryToGetObject(T importObject)
{
T existingObject = this.CompiledQueryGetObject(this.Context, importObject);
return existingObject;
}
#endregion Public methods
}
}
DerivedClass<SomeEntityType>
namespace MyNamespace
{
/// <
summary
>
/// Provides methods to access the SomeEntityType database table.
/// </
summary
>
public class DerivedClass : BaseClass<
SomeEntityType
>
{
#region Compiled queries
/// <
summary
>
/// A compiled query to look for an entity by its unique identifier(s) column(s).
/// </
summary
>
private static readonly Func<
SomeObjectContext
, SomeEntityType, SomeEntityType> m_LocalCompiledQueryGetObject = CompiledQuery.Compile<
SomeObjectContext
, SomeEntityType, SomeEntityType>(
(context, importSomeEntityType) => context.SomeEntityTypes.SingleOrDefault(someEntityInstance => someEntityInstance.ItemId == importSomeEntityType.ItemId));
#endregion Compiled queries
#region Constants
/// <
summary
>
/// The EntitySetName of the processor that is accessed by this class.
/// </
summary
>
private const string LocalEntitySetName = "SomeEntityType";
#endregion Constants
#region Constructor
/// <
summary
>
/// Creates a new instance of type DerivedClass.
/// </
summary
>
/// <
param
name
=
"context"
>The current database context.</
param
>
public DerivedClass(SomeObjectContext context)
: base(context)
{
}
#endregion Constructor
#region Properties
/// <
summary
>
/// Compiled query to get an object by the unique database constraint; Is overriden in derived classes.
/// </
summary
>
protected override Func<
SomeObjectContext
, SomeEntityType, SomeEntityType> CompiledQueryGetObject
{
get
{
return DerivedClass.m_LocalCompiledQueryGetObject;
}
}
#endregion Properties
}
}
The test class:
namespace TestProject1
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
// Arrange
// -------
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew, TimeSpan.FromSeconds(300)))
{
SomeObjectContext mockedContext = Mock.Create<
SomeObjectContext
>(Constructor.Mocked, Behavior.CallOriginal);
SomeEntityType emptyQueryObject = new SomeEntityType();
emptyQueryObject.ItemId = 1;
emptyQueryObject.CountryId = 1;
emptyQueryObject.StyleColorSetId = 1;
SomeEntityType returnThisObject = new SomeEntityType();
returnThisObject.ItemId = 2;
returnThisObject.CountryId = 2;
returnThisObject.StyleColorSetId = 2;
DerivedClass classUnderTest = new DerivedClass(mockedContext);
// System.ArgumentException: Direct null valued argument for non-public member is not supported. Use ArgExpr.IsNull<
T
>() or other members from ArgExpr wrapper class to provide your specification.
Mock.NonPublic.Arrange<
DerivedClass
>(classUnderTest, "m_LocalCompiledQueryGetObject", Arg.IsAny<
SomeObjectContext
>(), Arg.IsAny<
SomeEntityType
>())
.IgnoreArguments()
.Returns(CompiledQuery.Compile<
SomeObjectContext
, SomeEntityType, SomeEntityType>(
(paramContext, importSomeEntityType) => mockedContext.SomeEntityTypes.SingleOrDefault(someEntityInstance => someEntityInstance.ItemId == importSomeEntityType.ItemId)));
//Test method TestProject1.UnitTest1.TestMethod1 threw exception:
//System.ArgumentException: Expression of type 'System.Func`3[MyNamespace.SomeObjectContext,MyNamespace.SomeEntityType,MyNamespace.SomeEntityType]' cannot be used for return type 'MyNamespace.SomeEntityType'
Mock.NonPublic.Arrange<
SomeEntityType
>(classUnderTest, "CompiledQueryGetObject")
.IgnoreArguments()
.Returns(returnThisObject);
// This one is only possible if I set "InternalsVisibleTo" attribute and use the DerivedClass_Accessor instead
//// Test method TestProject1.UnitTest1.TestMethod1 threw exception:
//// System.ArgumentException: Direct null valued argument for non-public member is not supported. Use ArgExpr.IsNull<
T
>() or other members from ArgExpr wrapper class to provide your specification.
Mock.Arrange(() => classUnderTest.CompiledQueryGetObject(Arg.IsAny<
SomeObjectContext
>(), Arg.IsAny<
SomeEntityType
>()))
.IgnoreArguments()
.Returns(returnThisObject);
// Act
// -------
SomeEntityType receivedObject = classUnderTest.TryToGetObject(emptyQueryObject);
// Assert
// ------
Assert.IsNotNull(receivedObject);
// Some more Asserts...
}
}
private SomeEntityType returnEntity()
{
SomeEntityType returnObject = new SomeEntityType();
return returnObject;
}
}
}