Câu hỏi phỏng vấn Software Testing
Câu hỏi

How to unit test an object with database queries?

Câu trả lời

Unit testing an object with database queries can be approached in several ways, each with its own advantages and disadvantages. Here are the primary methods:

1. Mocking the Database

Pros:

  • Speed: Tests run faster because they do not involve actual database operations.
  • Isolation: Tests are isolated from external dependencies, ensuring that failures are due to code issues rather than database problems.
  • Consistency: Tests are consistent and repeatable, as they do not depend on the state of an external database.

Cons:

  • False Security: Mocking can give a false sense of security because it does not test the actual database interactions.
  • Maintenance: Mock objects need to be maintained and updated as the database schema or logic changes.

Example:

csharp Copy
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System.Collections.Generic;
using System.Linq;

[TestClass]
public class UserRepositoryTest
{
    [TestMethod]
    public void GetUsers_MustReturnUsersAsExpectedTest()
    {
        var mockSet = new Mock<DbSet<User>>();
        var data = new List<User>
        {
            new User { Id = 1, Username = "TestUser1", Password = "Password1" },
            new User { Id = 2, Username = "TestUser2", Password = "Password2" }
        }.AsQueryable();

        mockSet.As<IQueryable<User>>().Setup(m => m.Provider).Returns(data.Provider);
        mockSet.As<IQueryable<User>>().Setup(m => m.Expression).Returns(data.Expression);
        mockSet.As<IQueryable<User>>().Setup(m => m.ElementType).Returns(data.ElementType);
        mockSet.As<IQueryable<User>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());

        var mockContext = new Mock<YourDbContext>();
        mockContext.Setup(c => c.Users).Returns(mockSet.Object);

        var repository = new UserRepository(mockContext.Object);
        var users = repository.GetUsers();

        Assert.AreEqual(2, users.Count());
        Assert.AreEqual("TestUser1", users.First().Username);
    }
}

This example uses Moq to mock the DbSet<User> and YourDbContext to test the UserRepository without hitting the actual database[16].

2. Using an In-Memory Database

Pros:

  • Closer to Production: Tests are closer to real-world scenarios as they interact with an actual database.
  • No External Dependencies: No need for a separate test database setup.

Cons:

  • Limited Features: In-memory databases might not support all features of the production database.
  • Performance: Slower than mocking because it involves actual database operations.

Example:

python Copy
import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from yourapp.models import Base, User
from yourapp.repository import UserRepository

@pytest.fixture(scope='module')
def test_engine():
    engine = create_engine('sqlite:///:memory:')
    Base.metadata.create_all(engine)
    return engine

@pytest.fixture(scope='module')
def session(test_engine):
    Session = sessionmaker(bind=test_engine)
    return Session()

def test_get_users(session):
    user1 = User(username="TestUser1", password="Password1")
    user2 = User(username="TestUser2", password="Password2")
    session.add(user1)
    session.add(user2)
    session.commit()

    repository = UserRepository(session)
    users = repository.get_users()

    assert len(users) == 2
    assert users[0].username == "TestUser1"

This example uses SQLAlchemy with an in-memory SQLite database to test the UserRepository[17].

3. Using a Test Database

Pros:

  • Realistic: Tests interact with a real database, providing the most accurate results.
  • **Comprehensive...
junior

junior

Gợi ý câu hỏi phỏng vấn

middle

What is a reasonable Code Coverage % for unit tests (and why)?

senior

What is Spike Testing?

junior

What is profiling?

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào