Unit Testing EF Management Code

I am writing a bunch of unit tests for my ASP.NET MVC application using Entity Framework (against SQL Server database).

I use Rowan Miller's excellent Nuget packages "EntityFramework.Testing" and "EntityFramework.Testing.Moq" to allow me to unit test the EF code (without the actual SQL Server database).

This is my NUnit 3.5 test mount (in fact, it has a lot more tests, but it's just to show how everything is configured):

[TestFixture]
public class ContactsUseCaseTests : MyUnitTestBase
{
    private Mock<MyModel> _mockDbContext;
    private MockDbSet<Contact> _mockDbSetContact;
    private IContactsUseCase _usecase;

    [SetUp]
    public void InitializeTest()
    {
        SetupTestData();
        _usecase = new ContactsUseCase(_mockDbContext.Object);
    }

    [Test]
    public void TestSaveEntryNotNewButNotFound()
    {
        // Arrange
        Contact contact = new Contact { ContactId = 99, FirstName = "Leo", LastName = "Miller" };

        // Act
        _usecase.SaveContact(contact, false);

        // Assert
        _mockDbSetContact.Verify(x => x.Add(It.IsAny<Contact>()), Times.Once);
        _mockDbContext.Verify(x => x.SaveChanges(), Times.Once);
    }

    private void SetupTestData()
    {
        var contacts = new List<Contact>();

        contacts.Add(new Contact { ContactId = 12, FirstName = "Joe", LastName = "Smith" });
        contacts.Add(new Contact { ContactId = 17, FirstName = "Daniel", LastName = "Brown" });
        contacts.Add(new Contact { ContactId = 19, FirstName = "Frank", LastName = "Singer" });

        _mockDbSetContact = new MockDbSet<Contact>()
            .SetupAddAndRemove()
            .SetupSeedData(contacts)
            .SetupLinq();

        _mockDbContext = new Mock<MyModel>();
        _mockDbContext.Setup(c => c.ContactList).Returns(_mockDbSetContactList.Object);
        _mockDbContext.Setup(c => c.Contact).Returns(_mockDbSetContact.Object);
    }
}

As you can see, in the method [SetUp]I call SetupTestData, which creates Mock<MyModel>to mock the whole DbContext, and it sets MockDbSet<Contact>to handle my contacts.

- SaveContact :

public void SaveContact(Contact contactToSave, bool isNew) {
    if (isNew) {
        ModelContext.Contact.Add(contactToSave);
    } else {
        ModelContext.Entry(contactToSave).State = EntityState.Modified;
    }
    ModelContext.SaveChanges();
}

, Contact, , , , State Modified EF .

, , , , .

, , EF Mocking? ?

ModelContext.Entry(contactToSave).State = EntityState.Modified;
+4
1

DbContext.Entry , moq .

unit test EF, Microsoft . EF, .

, .

public interface IMyModelContext : IDisposable {
    DbSet<Contact> Contact { get; }
    int SaveChanges();
    DbEntityEntry Entry(object entity);
    DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class;
    //..other needed members
}

public partial class MyModel : DbContext, IMyModelContext {
    //...
}

, .

public class ContactsUseCase {
    private readonly IMyModelContext ModelContext;

    public ContactsUseCase(IMyModelContext context) {
        ModelContext = context;
    }

    //...
}

db, , .

[TestFixture]
public class ContactsUseCaseTests : MyUnitTestBase {
    private Mock<IMyModelContext> _mockDbContext;
    private MockDbSet<Contact> _mockDbSetContact;
    private IContactsUseCase _usecase;

    [SetUp]
    public void InitializeTest() {
        SetupTestData();
        _usecase = new ContactsUseCase(_mockDbContext.Object);
    }

    [Test]
    public void TestSaveEntryNotNewButNotFound() {
        // Arrange
        Contact contact = new Contact { ContactId = 99, FirstName = "Leo", LastName = "Miller" };

        // Act
        _usecase.SaveContact(contact, false);

        // Assert
        _mockDbSetContact.Verify(x => x.Add(It.IsAny<Contact>()), Times.Never);
        _mockDbContext.Verify(x => x.SaveChanges(), Times.Once);
    }

    private void SetupTestData() {
        var contacts = new List<Contact>();

        contacts.Add(new Contact { ContactId = 12, FirstName = "Joe", LastName = "Smith" });
        contacts.Add(new Contact { ContactId = 17, FirstName = "Daniel", LastName = "Brown" });
        contacts.Add(new Contact { ContactId = 19, FirstName = "Frank", LastName = "Singer" });

        _mockDbSetContact = new MockDbSet<Contact>()
            .SetupAddAndRemove()
            .SetupSeedData(contacts)
            .SetupLinq();

        _mockDbContext = new Mock<IMyModelContext>();
        _mockDbContext.Setup(c => c.ContactList).Returns(_mockDbSetContactList.Object);
        _mockDbContext.Setup(c => c.Contact).Returns(_mockDbSetContact.Object);

        _mockDbContext.Setup(c => c.Entry(It.IsAny<Contact>()).Returns(new DbEntityEntry());
    }
}
+1

Source: https://habr.com/ru/post/1689568/


All Articles