chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
Welcome to Typemock Community! Here you can ask and receive answers from other community members. If you liked or disliked an answer or thread: react with an up- or downvote.
0 votes
I'm running the evaluation of TypeMock Isolator to see if I can run tests on a simple graph of Entity Framework 3.5 objects without having to access the database, but I'm having problems assembling a parent-child graph correctly.

I have a Parent EF object which contains a navigation to an EntityCollection of Child objects. I'm trying to pass the faked Parent (with faked Children) to a Business Object which reads the child objects, but I can't seem to get the child objects to appear in the mocked parent.

In this example, I'm trying to test my business method, "DoSomeStuff", which in turn calls "RetrieveParentsToDoSomeStuff". It also calls the auto-generated Entity Framework "Parent.Children" to retrieve an EntityCollection of children. The problem is that the parent.Children collection doesn't contain my dummy child collection, even though my assertion passes that "Children.Load" is called. (I'm not sure how to assert that "parent.Children" returned a non-zero-length collection, but I can see that this is the case in the debugger.)

Is this the correct way to do this? I also tried using real EntityObjects, but the ObjectContext seemed to think that they hadn't been initialized properly (it complained that they seemed to be from another ObjectContext).

I've seen http://mosesofegypt.net/post/Introducin ... lator.aspx, but there the ObjectContext is modified; I'm trying to avoid that in my tests....


// Create a Child entity object
Child dummyChild = Isolate.Fake.Instance<Child>();                
dummyChild.Value1 = 1;
dummyChild.Value2 = 2;

// put it in a collection
IQueryable<Child> fakedChildren = (new List<Child> { child }).AsQueryable();
               
// Create a Parent entity object
Parent dummyParent = Isolate.Fake.Instance<Parent>();
dummyParent.Name = "Dummy Parent";

// ReSharper disable ConverClosureToMethodGroup
Isolate.WhenCalled(() => dummyParent.Children.IsLoaded).WillReturn(false);
Isolate.WhenCalled(() => dummyParent.Children.Load()).IgnoreCall();
Isolate.WhenCalled(() => dummyParent.Children).WillReturnCollectionValuesOf(fakedChildren);

// Make a collection of the one Parent
List<Parent> fakedParents = new List<Parent>
{
  dummyParent
};

// Intercept the internal call and replace the return value with our fakeParents.

Isolate.NonPublic.WhenCalled(businessObject, "RetrieveParentsToDoSomeStuff").WillReturn(  fakedParents);

// *** ACT ***

// DoSomeStuff will call "RetrieveParentsToDoSomeStuff"

bool stuffDone = businessObject.DoSomeStuff();

// *** ASSERT ***

Isolate.Verify.WasCalledWithAnyArguments(() => dummyParent.Children.Load());

// *** I can't figure out how to assert that dummyParent.Children actually 
// returned an non-zero-length EntityCollection, but I can see that it 
// contains no elements in the debugger.


asked by mikebridge (760 points)

3 Answers

0 votes
Hi Mike, and welcome to Isolator.

Unfortunately, I don't know of a way of isolating EF behavior without faking ObjectContext. The problem with ObjectContext is that its construction defines external dependencies (usually database), so it should be faked out in order to keep your unit test isolated.

Can you try faking out the ObjectContext? Moses' guidance in the blog post you linked to is pretty detailed as to the technique.

Thanks,
Doron
Typemock Support
answered by doron (16.5k points)
0 votes
Ok, I think I see the problem:

IQueryable<Child> fakedChildren = (new List<Child> { child }).AsQueryable(); 


It appears that the reason why my parent.Children collection is empty is because of the conversion to IQueryable. I think it's not executing the "query" wrapper around the list. I fixed this by keeping it as a List (despite the fact that the blog I referenced indicated that this caused an Exception in the version he was using):

List<Child> fakedChildren = (new List<Children> { child });


Anyway, the reason I was hoping to avoid faking the ObjectContext was that in my architecture the ObjectContext creation is completely decoupled from the client so that ObjectContexts can be managed in different ways for different environments---testing, windows application or webapp. At the time it seemed like it would require adding a testing hook in the code in order to fake it (thus defeating AAA), but I have since discovered Isolate.Swap.NextInstance, which looks like it would probably address that issue, too.

Thanks!

-Mike



Hi Mike, and welcome to Isolator.

Unfortunately, I don't know of a way of isolating EF behavior without faking ObjectContext. The problem with ObjectContext is that its construction defines external dependencies (usually database), so it should be faked out in order to keep your unit test isolated.

Can you try faking out the ObjectContext? Moses' guidance in the blog post you linked to is pretty detailed as to the technique.

Thanks,
Doron
Typemock Support
answered by mikebridge (760 points)
0 votes
Oh, and I should also mention that I didn't need to fake any objects once I discovered that issue. I was able to instantiate real objects and just modify their behaviour slightly.

On a related note, someone from the EF team suggests that you create a "Metadata-only Connection" in order to keep a real ObjectContext around for testing, but without doing any DB calls:

http://blogs.msdn.com/diego/archive/200 ... asses.aspx
answered by mikebridge (760 points)
...