Unit testing is essential for building reliable and maintainable .NET applications. Whether you're just getting started with ๐ ๐จ๐ป๐ถ๐ or want to sharpen your test-writing approach, here are ๐ญ๐ฌ ๐ฏ๐ฒ๐๐ ๐ฝ๐ฟ๐ฎ๐ฐ๐๐ถ๐ฐ๐ฒ๐ every .NET developer should follow.
โ ๐ญ. ๐๐๐ผ๐ถ๐ฑ ๐๐ป๐ณ๐ฟ๐ฎ๐๐๐ฟ๐๐ฐ๐๐๐ฟ๐ฒ ๐๐ฒ๐ฝ๐ฒ๐ป๐ฑ๐ฒ๐ป๐ฐ๐ถ๐ฒ๐
- Tests should be fast and isolated.
- Use Dependency Injection.
- Separate unit tests from integration tests in different projects.
โ
๐ฎ. ๐๐ผ๐น๐น๐ผ๐ ๐ง๐ฒ๐๐ ๐ก๐ฎ๐บ๐ถ๐ป๐ด ๐ฆ๐๐ฎ๐ป๐ฑ๐ฎ๐ฟ๐ฑ๐
Structure test names as:
MethodName_Scenario_ExpectedBehavior()
๐๐ ๐ฎ๐บ๐ฝ๐น๐ฒ:
[Fact]
public void Add_SingleNumber_ReturnsSameNumber()
โ
๐ฏ. ๐จ๐๐ฒ ๐๐ฟ๐ฟ๐ฎ๐ป๐ด๐ฒ, ๐๐ฐ๐, ๐๐๐๐ฒ๐ฟ๐ (๐๐๐)
Make your tests easier to read and maintain.
๐๐ ๐ฎ๐บ๐ฝ๐น๐ฒ:
[Fact]
public void Add_EmptyString_ReturnsZero()
{
var calculator = new StringCalculator(); // Arrange
var result = calculator.Add(""); // Act
Assert.Equal(0, result); // Assert
}
โ
๐ฐ. ๐ช๐ฟ๐ถ๐๐ฒ ๐ ๐ถ๐ป๐ถ๐บ๐ฎ๐น๐น๐ ๐ฃ๐ฎ๐๐๐ถ๐ป๐ด ๐ง๐ฒ๐๐๐
Use the simplest inputs necessary to validate the behavior.
๐ฃ๐ฟ๐ฒ๐ณ๐ฒ๐ฟ:
calculator.Add("0");
๐ข๐๐ฒ๐ฟ:
calculator.Add("42");
โ
๐ฑ. ๐๐๐ผ๐ถ๐ฑ ๐ ๐ฎ๐ด๐ถ๐ฐ ๐ฆ๐๐ฟ๐ถ๐ป๐ด๐
Use well-named constants for readability and clarity.
๐๐ป๐๐๐ฒ๐ฎ๐ฑ ๐ผ๐ณ:
calculator.Add("1001");
๐จ๐๐ฒ:
const string MAX_INPUT = "1001";
calculator.Add(MAX_INPUT);
โ
๐ฒ. ๐๐๐ผ๐ถ๐ฑ ๐๐ผ๐ด๐ถ๐ฐ ๐ถ๐ป ๐ง๐ฒ๐๐๐
No loops, conditionals, or switch statements.
๐ฃ๐ฟ๐ฒ๐ณ๐ฒ๐ฟ:
[Theory]
[InlineData("1,2,3", 6)]
[InlineData("4,5", 9)]
๐ข๐๐ฒ๐ฟ:
foreach (var test in testCases) { ... }
โ
๐ณ. ๐จ๐๐ฒ ๐๐ฒ๐น๐ฝ๐ฒ๐ฟ ๐ ๐ฒ๐๐ต๐ผ๐ฑ๐ ๐๐ป๐๐๐ฒ๐ฎ๐ฑ ๐ผ๐ณ ๐ฆ๐ฒ๐๐๐ฝ/๐ง๐ฒ๐ฎ๐ฟ๐๐ผ๐๐ป
xUnit doesnโt use [SetUp]
and [TearDown]
.
Use constructors or private methods.
๐๐ ๐ฎ๐บ๐ฝ๐น๐ฒ:
private StringCalculator CreateDefaultStringCalculator()
{
return new StringCalculator();
}
โ
๐ด. ๐๐๐ผ๐ถ๐ฑ ๐ ๐๐น๐๐ถ๐ฝ๐น๐ฒ ๐๐ฐ๐ ๐ฆ๐๐ฒ๐ฝ๐
Each test should validate a single action only.
๐๐ป๐๐๐ฒ๐ฎ๐ฑ ๐ผ๐ณ:
var result1 = calculator.Add("");
var result2 = calculator.Add(",");
๐ฆ๐ฝ๐น๐ถ๐ ๐ถ๐ป๐๐ผ ๐๐ฒ๐ฝ๐ฎ๐ฟ๐ฎ๐๐ฒ ๐๐ฒ๐๐ ๐ฐ๐ฎ๐๐ฒ๐ ๐ผ๐ฟ ๐๐๐ฒ:
[Theory]
[InlineData("", 0)]
[InlineData(",", 0)]
โ
๐ต. ๐ง๐ฒ๐๐ ๐ฃ๐ฟ๐ถ๐๐ฎ๐๐ฒ ๐ ๐ฒ๐๐ต๐ผ๐ฑ๐ ๐๐ถ๐ฎ ๐ฃ๐๐ฏ๐น๐ถ๐ฐ ๐ ๐ฒ๐๐ต๐ผ๐ฑ๐
Avoid direct testing of private methods.
Test them through public behavior.
๐๐ ๐ฎ๐บ๐ฝ๐น๐ฒ:
Assert.Equal("a", parser.ParseLogLine(" a "));
โ
๐ญ๐ฌ. ๐๐ฎ๐ป๐ฑ๐น๐ฒ ๐ฆ๐๐ฎ๐๐ถ๐ฐ ๐๐ฒ๐ฝ๐ฒ๐ป๐ฑ๐ฒ๐ป๐ฐ๐ถ๐ฒ๐ ๐๐ฎ๐ฟ๐ฒ๐ณ๐๐น๐น๐
Wrap static calls in abstractions and inject them so you can mock them during testing.
๐ช๐ต๐ถ๐ฐ๐ต ๐ผ๐ณ ๐๐ต๐ฒ๐๐ฒ ๐ฝ๐ฟ๐ฎ๐ฐ๐๐ถ๐ฐ๐ฒ๐ ๐ต๐ฎ๐ ๐บ๐ฎ๐ฑ๐ฒ ๐๐ต๐ฒ ๐ฏ๐ถ๐ด๐ด๐ฒ๐๐ ๐ฑ๐ถ๐ณ๐ณ๐ฒ๐ฟ๐ฒ๐ป๐ฐ๐ฒ ๐ถ๐ป ๐๐ผ๐๐ฟ ๐๐ฒ๐๐๐ถ๐ป๐ด ๐ฎ๐ฝ๐ฝ๐ฟ๐ผ๐ฎ๐ฐ๐ต?
๐๐ผ ๐๐ผ๐ ๐ณ๐ผ๐น๐น๐ผ๐ ๐ฎ๐ป๐ ๐ผ๐๐ต๐ฒ๐ฟ ๐
๐จ๐ป๐ถ๐ ๐ผ๐ฟ ๐๐ฒ๐๐๐ถ๐ป๐ด ๐๐๐ฟ๐ฎ๐๐ฒ๐ด๐ถ๐ฒ๐ ๐๐ต๐ฎ๐ ๐๐ผ๐ ๐๐๐ฒ๐ฎ๐ฟ ๐ฏ๐?
Top comments (0)