跳到主要内容

Testing Stack

Think of testing in 3 layers:

Unit Tests
├─ FluentAssertions (expressive checks)
├─ Moq (isolate dependencies)
└─ AutoFixture (generate data)

Integration Tests
└─ WebApplicationFactory + HttpClient

Fluent Assertions (FA) — How You Assert

What it is (interview one-liner)

FluentAssertions makes test assertions readable and expressive, closer to natural language.

Why people love it

  • Clear failure messages
  • Self-documenting tests
  • Less "mental translation" than Assert.Equal

Compare with xUnit Assert

Assert.Equal(5, result);

vs

result.Should().Be(5);

The second one reads like English.


Core FluentAssertions You MUST Remember

✅ Basic

result.Should().Be(5);
result.Should().NotBe(10);
result.Should().BeTrue();
result.Should().BeNull();

✅ Collections

list.Should().HaveCount(3);
list.Should().Contain("apple");
list.Should().BeEquivalentTo(new[] {1,2,3}); // order ignored

✅ Strings

name.Should().StartWith("John");
name.Should().Contain("Middle");

✅ Exceptions ⭐

Action act = () => method();
act.Should().Throw<ArgumentException>()
.WithMessage("Invalid operation");

📌 Interview line:

"FluentAssertions improves readability and produces better failure messages."


AutoFixture — How You Create Test Data

What problem it solves

"I don't want to manually create objects with 10 properties every test."

What it does

  • Auto-creates objects
  • Fills properties with sensible values
  • Removes boilerplate

Typical usage with xUnit

[Theory, AutoData]
public void CreatePerson_ValidInput(Person person)
{
person.Should().NotBeNull();
}

AutoFixture creates Person automatically


When AutoFixture shines

  • Large DTOs
  • Nested objects
  • Parameterized tests

📌 Interview line:

"AutoFixture reduces test setup noise and encourages broader test coverage."


Mocking — How You Isolate Units

Why mocking exists

Unit tests should:

  • ❌ Not hit DB
  • ❌ Not call APIs
  • ❌ Not rely on infrastructure

Mock dependencies


Moq — How You Mock in .NET

Typical Moq Flow (Memorize This)

Create mock
→ Setup behavior
→ Inject mock
→ Verify interaction

Example

var repoMock = new Mock<IPersonsRepository>();

repoMock.Setup(r => r.AddPerson(It.IsAny<Person>()))
.ReturnsAsync(person);

Inject:

var service = new PersonsService(repoMock.Object);

Verify:

repoMock.Verify(r => r.AddPerson(It.IsAny<Person>()), Times.Once);

📌 Interview line:

"Moq allows us to control dependency behavior and verify interactions."


What NOT to Mock ❌

  • The class under test
  • Value objects
  • Simple logic

Mock boundaries, not internals.


Unit Tests vs Integration Tests (BIG INTERVIEW FAVORITE)

Unit TestIntegration Test
FastSlower
IsolatedReal pipeline
Mock dependenciesReal DI
Test logicTest flow

Integration Tests in ASP.NET Core

What They Test

  • Routing
  • Model binding
  • Controllers + Services
  • Views / API responses
  • DB interaction

Tools Used

ToolPurpose
WebApplicationFactoryTest server
HttpClientSend requests
InMemory DBIsolated DB
FluentAssertionsAssertions

CustomWebApplicationFactory ⭐

public class CustomWebApplicationFactory
: WebApplicationFactory<Program>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.UseEnvironment("Test");

builder.ConfigureServices(services =>
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseInMemoryDatabase("TestDb"));
});
}
}

📌 Why this matters:

It spins up the real app, but safely.


Integration Test Example

HttpResponseMessage response = await _client.GetAsync("/Persons/Index");

response.Should().BeSuccessful();

string html = await response.Content.ReadAsStringAsync();
html.Should().Contain("<table");

📌 You're testing what the user actually gets.


When to Use What (Very Important)

Use Unit Tests when:

  • Testing business logic
  • Testing validation
  • Testing edge cases

Use Integration Tests when:

  • Testing full request flow
  • Testing EF + DI + routing
  • Testing views / APIs

Best Practices (Memorize This List)

✅ Use FluentAssertions for readability ✅ Use AutoFixture to reduce setup noise ✅ Mock external dependencies ✅ Prefer unit tests for logic ✅ Use integration tests for confidence ❌ Don't mock everything ❌ Don't over-verify implementation


9️⃣ One-Paragraph Interview Answer

"In ASP.NET Core, we use FluentAssertions for readable and expressive assertions, AutoFixture to reduce test data boilerplate, and Moq to isolate dependencies in unit tests. Unit tests verify business logic in isolation, while integration tests use WebApplicationFactory and HttpClient to test the full request pipeline, often with an in-memory database. Together, they provide fast feedback and confidence in real-world behavior."


If You Remember ONLY 6 Things

  1. FluentAssertions = readable assertions
  2. AutoFixture = auto test data
  3. Moq = isolate dependencies
  4. Unit tests = logic
  5. Integration tests = flow
  6. WebApplicationFactory = real app in tests