Should I mock the entities of EF when unit testing

2019-08-08 10:40发布

问题:

I read this post about mocking Entity Framework(EF).

Shouldn't we abstract the entities' types as well? In order to preserve decoupling between the Data Access Layer (DAL) and the Business Layer (BL)?

In the above post, he used EF concrete generated entities types:

[TestMethod]
public void GetCustomer()
{
    ContextContainerMock container = new ContextContainerMock();
    IMyEntities en = container.Current;

**Customer c = new Customer { ID = 1, FirstName = "John", LastName = "Doe" };**
    en.Customers.AddObject(c);

    CustomerService service = new CustomerService(container);
    var a = service.GetCustomer(1);

    Assert.AreEqual(c.FirstName, a.FirstName);
    Assert.AreEqual(c.LastName, a.LastName);
}

回答1:

Personally, I don't mock these. I create, test and cleanup directly. This has helped me catch problem that are more real world scenarios when dealing with the database. Mocking is fantastic for testing integrations where you may not have access to a resource like a DB. If this is your case, then you may have no choice. Hope that helps.



回答2:

The short answer is no.

The entities, if done correctly, don't depend on any other code, except other entities and value objects (such as string, int, or your own value object). Therefore, there's no need to mock them.

Also, the entities are part of the core of your system. They are what your system is all about. You'd typically want to test what the system behaves like when operating on these classes rather than testing when the system behaves like when operating on what the tests say they behave like.

(As a side note, your entities ought to look like and behave like something that exists in the real world. That is, you should be able to reason about the behavior with a non-technical person from the business side of the organisation. From your example I see that it is possible to create a Customer without a name. Is that ok from a business point of view? If not, I'd say you should have the constructor take the first and last name as argument.)