开发者

Unit testing with FakeItEasy against nested Entity Framework member

开发者 https://www.devze.com 2023-03-27 19:22 出处:网络
We are trying to unit test code that relies on the Entity Framework 4.1.I\'ve seen several posts that implement unit testing against POCOs, but we would like to retain the default EF plumbing, so that

We are trying to unit test code that relies on the Entity Framework 4.1. I've seen several posts that implement unit testing against POCOs, but we would like to retain the default EF plumbing, so that we can easily use the EF Caching Wrapper.

FakeItEasy seems to handle abstracting away EF okay, but I'm having problems asserting what happened. For example, I have this code in my model (where there is another Email partial class that is the autogenerated code from the EF database-first wizard):

public partial class Email 
{
    IMyEntities _dataContext;

    public Email(IMyEntities myEntities)
    {
        _dataContext = myEntities;
    }
    public void SendEmails()
    {
        // ... code to send emails goes here...
        _dataContext.Emails.AddObject(this);
        _dataContext.SaveChanges();
    }
}

Then in my unit test with FakeItEasy:

var context = A.Fake<IMyEntities>();
var email = A.Fake<Email>(context);
// ... code to configure email goes here ...
email.SendEmails();

// this fails with a FakeItEasy.ExpectationException...
A.CallTo(开发者_JAVA技巧() => context.Email.AddObject(email)).MustHaveHappened();

How can I know from my unit test that context.Emails.AddObject actually did get called?

Thank you!


You need to set the Email-property of you context to a fake:

var context = A.Fake<IMyEntities>();
var mail = A.Fake<WhateverTypeTheEmailPropertyHas>();
A.CallTo(() => context.Email).Returns(mail);

var email = A.Fake<Email>(context);
// ... code to configure email goes here ...
email.SendEmails();

// this fails with a FakeItEasy.ExpectationException...
A.CallTo(() => mail.AddObject(email)).MustHaveHappened();

Now I guess it should work.


I found a workaround that I'm not crazy about, but it does work. Instead of calling AddObject() on the child object, you can call a deprecated method, AddTo[Collection Name](), on the data context itself. Since this is just a shallow method call, it can be easily evaluated by FakeItEasy.

My code changed to this:

public void SendEmails()
{
    // ... code to send emails goes here...
    _dataContext.AddToEmails(this);
    _dataContext.SaveChanges();
}

Then, in my unit test:

A.CallTo(_dataContext).Where(m => m.Method.Name == "AddToEmails").MustHaveHappened();
A.CallTo(() => _dataContext.SaveChanges()).MustHaveHappened();

Of course, by doing this you have the downside of always ignoring the preferred, non-deprecated, methods whenever you want to add to a collection of the data context. Not to mention, there's a good chance I'll get tripped up later on with a need to determine execution on a child object's method...

If anyone knows a better way, please share!

Thank you,

Eric

0

精彩评论

暂无评论...
验证码 换一张
取 消