Home Products Download Learn Buy Now Why Typemock? Support & Community About
Community > Forum
 FAQFAQ    SearchSearch   RegisterRegister   RssRss   ProfileProfile   Log inLog in 

Mocking Entity Framework DataContext?

 
Post new topic   Reply to topic    Typemock Forum Index -> Beginners
View previous topic :: View next topic  
Author Message
petteroe
Advanced
Advanced


Joined: 25 May 2007
Posts: 15

PostPosted: Fri Mar 28, 2008 11:30 am    Post subject: Mocking Entity Framework DataContext? Reply with quote

Hi,

I am trying to mock the call to the SaveChanges method on a Entity Framework data context object.

Here is the method to test:

Code:

      public static Account AddNewAccount(Account newAccount)
      {
         if (newAccount.ID == 0)
            throw new AccountCreationException(ReturnCodes.AccountIDAlreadyExists, null, newAccount);

         try
         {
            using (CoreAccountsEntities db = new CoreAccountsEntities())
            {
               db.AddToAccount(newAccount);
               db.SaveChanges();
               return newAccount;
            }
         }
         catch (Exception ex)
         {
            throw new AccountCreationException(ReturnCodes.GeneralError, ex, newAccount);
         }
      }


In this method, I want to mock the db.SaveChanges, and the return of the newAccount now populated with a new ID. Here is the test I have made so far:

Code:


      [TestMethod]
      [VerifyMocks]
      public void AddAccountSavesNewAccountToDatabaseAndReturnsNewAccountWithAccountID()
      {
         Account newAccount = new Account();
         newAccount.AccountName = "New unit test account";
         newAccount.CannotHaveInternalTransactions = true;
         newAccount.CanOverdraft = false;
         newAccount.CanReceive = true;
         newAccount.CanReceiveBankTransactions = false;
         newAccount.CanReceiveCreditCardTransactions = false;
         newAccount.CanSend = true;
         newAccount.Currency = "EUR";
         newAccount.LastUpdated = DateTime.Now;
         newAccount.SupportsSMSBlock = false;

         Account savedAccount;
         savedAccount.ID = 1;
         savedAccount.AccountName = "New unit test account";
         savedAccount.CannotHaveInternalTransactions = true;
         newAcsavedAccountcount.CanOverdraft = false;
         savedAccount.CanReceive = true;
         savedAccount.CanReceiveBankTransactions = false;
         savedAccount.CanReceiveCreditCardTransactions = false;
         savedAccount.CanSend = true;
         savedAccount.Currency = "EUR";
         savedAccount.LastUpdated = DateTime.Now;
         savedAccount.SupportsSMSBlock = false;

         using (RecordExpectations recorder = RecorderManager.StartRecording())
            {
            CoreAccountsEntities db = new CoreAccountsEntities();
            db.  <== This is where the SaveChanges() method don't appear...
            }

         newAccount.ID = 1;
         Assert.AreEqual<Account>(newAccount, savedAccount);
      }


I have checked to see that the SaveChanges method is in fact public, so I am stuck. Please be kind as I am a total newbie with TypeMock... (and mocking in general)

Morten
Back to top
View user's profile Send private message
ohad
Site Admin
Site Admin


Joined: 18 May 2006
Posts: 683

PostPosted: Fri Mar 28, 2008 12:39 pm    Post subject: Reply with quote

Hi Morten
Welcome to the forum Cool
I assume that the test code is in separate assembly than the code under test.
First check if the test project has a reference to the Entity framework assembly (The same as the production code)
Than check if include the correct using for the namespace at the head of the code file.
Please tell me if it helps.
_________________
Regards

Ohad,
TypeMock Support Group
Back to top
View user's profile Send private message
petteroe
Advanced
Advanced


Joined: 25 May 2007
Posts: 15

PostPosted: Fri Mar 28, 2008 1:12 pm    Post subject: Reply with quote

Thanks Ohad,

I was so caught up in the new mocking stuff that I overlooked the basics. It turned out to be just a missing reference to the System.Data.Entity assembly.
Back to top
View user's profile Send private message
petteroe
Advanced
Advanced


Joined: 25 May 2007
Posts: 15

PostPosted: Fri Mar 28, 2008 3:16 pm    Post subject: How to use NaturalMocks to mock method on real instance? Reply with quote

I have a follow up question:

Using the same method and test as above, I need to have the test allow the CoreAccountsEntities actually be created (because it will load the mapping stuff and this is probably too much to mock), but also intercept the call to SaveChanges.

I tried to put this in the recorder using block:

Code:

CoreAccountsEntities db = new CoreAccountEntities();
db.SaveChanges();
recorder.Return(1);


but this throws a runtime error.

I then tried to pull the instantiation out of the using block like this:

Code:

CoreAccountsEntities db = new CoreAccountEtities();
using (RecordExpectations recorder = RecorderManager.StartRecording())
{
    db.SaveChanges();
    recorder.Return(1);
}


This fails with a message from TypeMock that one more call to SaveChanges() is expected, and also the data was saved to the database so the call was obviously not intercepted. I have no problem understanding why, because there is no way for the recorder to now which instance to call the SaveChanges method on. But how do I go about doing this?

Thanks,

Morten
Back to top
View user's profile Send private message
ohad
Site Admin
Site Admin


Joined: 18 May 2006
Posts: 683

PostPosted: Fri Mar 28, 2008 7:37 pm    Post subject: Reply with quote

Hi
Can you please post the error message you're getting in your first example?
i.e. when you do this:
Code:

CoreAccountsEntities db = new CoreAccountEntities();
db.SaveChanges();
recorder.Return(1);


Please tell me what line throws the runtime error.
_________________
Regards

Ohad,
TypeMock Support Group
Back to top
View user's profile Send private message
petteroe
Advanced
Advanced


Joined: 25 May 2007
Posts: 15

PostPosted: Sat Mar 29, 2008 9:06 am    Post subject: Reply with quote

The error occurs when I hit the db.AddToAccount(newAccount) line in the production code above.

Here is the error message:

Code:
Test method [...snipped namespace...].AccountOperationsTests.AddAccountSavesNewAccountToDatabaseAndReturnsNewAccountWithAccountID threw exception:  [...snipped namespace...].AccountCreationException: GeneralError --->  System.ArgumentNullException: Value cannot be null.
Parameter name: metadataWorkspace.


I am assuming that this error occurs because the mocked instance of the entity context has not been initialized with the proper mappings.


Thanks,

Morten
Back to top
View user's profile Send private message
ohad
Site Admin
Site Admin


Joined: 18 May 2006
Posts: 683

PostPosted: Sun Mar 30, 2008 12:30 pm    Post subject: Reply with quote

Hi Mortan
My guess is that since the constructor of CoreAccountEntities is mocked some
field in the class was not initiated properly and this is the cause to the exception.
By default the constructor of CoreAccountEntities is mocked. If you want to change that use recorder.CallOriginal after the call to the constructor.
Code:

CoreAccountsEntities db = new CoreAccountEntities();
recorder.CallOriginal();


Please tell me if it works.
_________________
Regards

Ohad,
TypeMock Support Group
Back to top
View user's profile Send private message
petteroe
Advanced
Advanced


Joined: 25 May 2007
Posts: 15

PostPosted: Sun Mar 30, 2008 1:07 pm    Post subject: Reply with quote

Thanks a lot Ohad,

That did the trick. I was looking for a "Use real constructor" type metod to instantiate the datacontext, but didn't give the CallOriginal behaviour credit for all that it can do... Great stuff.

The small downside to my specific scenario now is that I am relying on real mapping files for the entity framework being sucked into the mock. This is because I haven't found an easy way to isolate only the mappings needed for each test, and frankly I think that would have created a little too much work. So I am relying on a tiny bit of external configuration in my unit tests... So what! Wink
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Typemock Forum Index -> Beginners All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group