diff --git a/src/dotnet/QuantEngine.Web.Tests/DashboardComponentTests.cs b/src/dotnet/QuantEngine.Web.Tests/DashboardComponentTests.cs
new file mode 100644
index 0000000..7316e95
--- /dev/null
+++ b/src/dotnet/QuantEngine.Web.Tests/DashboardComponentTests.cs
@@ -0,0 +1,256 @@
+using Bunit;
+using MudBlazor;
+using Xunit;
+using QuantEngine.Web.Client.Pages;
+using QuantEngine.Web.Client.Components;
+
+namespace QuantEngine.Web.Tests;
+
+///
+/// Unit tests for Dashboard component using bUnit
+///
+public class DashboardComponentTests : TestContext
+{
+ [Fact]
+ public void Dashboard_Renders_Without_Errors()
+ {
+ // Arrange & Act
+ var cut = RenderComponent();
+
+ // Assert
+ cut.Markup.Should().Contain("관리자 대시보드");
+ }
+
+ [Fact]
+ public void Dashboard_Displays_KPI_Cards()
+ {
+ // Arrange & Act
+ var cut = RenderComponent();
+
+ // Assert - Should have 4 KPI cards
+ cut.FindAll(".mud-paper").Count.Should().BeGreaterThanOrEqualTo(4);
+ cut.Markup.Should().Contain("총 수집 실행");
+ cut.Markup.Should().Contain("성공률");
+ cut.Markup.Should().Contain("최근 에러");
+ cut.Markup.Should().Contain("마지막 동기화");
+ }
+
+ [Fact]
+ public void Dashboard_Shows_System_Status()
+ {
+ // Arrange & Act
+ var cut = RenderComponent();
+
+ // Assert
+ cut.Markup.Should().Contain("시스템 상태");
+ cut.Markup.Should().Contain("API 서버");
+ cut.Markup.Should().Contain("데이터베이스");
+ }
+
+ [Fact]
+ public void Dashboard_Has_Activity_Feed()
+ {
+ // Arrange & Act
+ var cut = RenderComponent();
+
+ // Assert
+ cut.Markup.Should().Contain("최근 활동");
+ }
+
+ [Fact]
+ public void Dashboard_Has_Collections_Table()
+ {
+ // Arrange & Act
+ var cut = RenderComponent();
+
+ // Assert
+ cut.Markup.Should().Contain("최근 데이터 수집 실행");
+ cut.Markup.Should().Contain("새로고침");
+ }
+}
+
+///
+/// Unit tests for FormField component
+///
+public class FormFieldComponentTests : TestContext
+{
+ [Fact]
+ public void FormField_Renders_Text_Input()
+ {
+ // Arrange
+ var parameters = new ComponentParameterCollection
+ {
+ { "Label", "사용자명" },
+ { "Type", "text" },
+ { "Placeholder", "이름 입력" }
+ };
+
+ // Act
+ var cut = RenderComponent(parameters);
+
+ // Assert
+ cut.Markup.Should().Contain("사용자명");
+ cut.Markup.Should().Contain("이름 입력");
+ }
+
+ [Fact]
+ public void FormField_Shows_Required_Indicator()
+ {
+ // Arrange
+ var parameters = new ComponentParameterCollection
+ {
+ { "Label", "이메일" },
+ { "Type", "email" },
+ { "Required", true }
+ };
+
+ // Act
+ var cut = RenderComponent(parameters);
+
+ // Assert
+ cut.Markup.Should().Contain("*");
+ }
+
+ [Fact]
+ public void FormField_Displays_Error_Message()
+ {
+ // Arrange
+ var parameters = new ComponentParameterCollection
+ {
+ { "Label", "비밀번호" },
+ { "Type", "password" },
+ { "ErrorMessage", "최소 8자 이상 입력하세요" }
+ };
+
+ // Act
+ var cut = RenderComponent(parameters);
+
+ // Assert
+ cut.Markup.Should().Contain("최소 8자 이상 입력하세요");
+ }
+
+ [Fact]
+ public void FormField_Shows_Help_Text()
+ {
+ // Arrange
+ var parameters = new ComponentParameterCollection
+ {
+ { "Label", "핸드폰" },
+ { "Type", "tel" },
+ { "HelpText", "하이픈 없이 숫자만 입력하세요" }
+ };
+
+ // Act
+ var cut = RenderComponent(parameters);
+
+ // Assert
+ cut.Markup.Should().Contain("하이픈 없이 숫자만 입력하세요");
+ }
+}
+
+///
+/// Unit tests for Portfolio component
+///
+public class PortfolioComponentTests : TestContext
+{
+ [Fact]
+ public void Portfolio_Renders_Without_Errors()
+ {
+ // Arrange & Act
+ var cut = RenderComponent();
+
+ // Assert
+ cut.Markup.Should().Contain("포트폴리오");
+ }
+
+ [Fact]
+ public void Portfolio_Displays_Summary_Cards()
+ {
+ // Arrange & Act
+ var cut = RenderComponent();
+
+ // Assert - Should have summary cards
+ cut.Markup.Should().Contain("총 평가액");
+ cut.Markup.Should().Contain("보유 종목");
+ cut.Markup.Should().Contain("수익률");
+ cut.Markup.Should().Contain("위험도");
+ }
+
+ [Fact]
+ public void Portfolio_Shows_Asset_Table()
+ {
+ // Arrange & Act
+ var cut = RenderComponent();
+
+ // Assert
+ cut.Markup.Should().Contain("자산 구성");
+ cut.Markup.Should().Contain("종목/펀드명");
+ cut.Markup.Should().Contain("평가액");
+ }
+
+ [Fact]
+ public void Portfolio_Shows_Asset_Classification()
+ {
+ // Arrange & Act
+ var cut = RenderComponent();
+
+ // Assert
+ cut.Markup.Should().Contain("자산 분류");
+ cut.Markup.Should().Contain("대형주");
+ cut.Markup.Should().Contain("중형주");
+ }
+
+ [Fact]
+ public void Portfolio_Shows_Trading_History()
+ {
+ // Arrange & Act
+ var cut = RenderComponent();
+
+ // Assert
+ cut.Markup.Should().Contain("거래 이력");
+ cut.Markup.Should().Contain("구분");
+ cut.Markup.Should().Contain("금액");
+ }
+}
+
+///
+/// Unit tests for NavMenu component
+///
+public class NavMenuComponentTests : TestContext
+{
+ [Fact]
+ public void NavMenu_Renders_Navigation_Links()
+ {
+ // Arrange & Act
+ var cut = RenderComponent();
+
+ // Assert
+ cut.Markup.Should().Contain("대시보드");
+ cut.Markup.Should().Contain("관리");
+ cut.Markup.Should().Contain("운영");
+ }
+
+ [Fact]
+ public void NavMenu_Has_Admin_Section()
+ {
+ // Arrange & Act
+ var cut = RenderComponent();
+
+ // Assert
+ cut.Markup.Should().Contain("사용자 관리");
+ cut.Markup.Should().Contain("데이터 수집");
+ cut.Markup.Should().Contain("설정");
+ }
+
+ [Fact]
+ public void NavMenu_Has_Help_Section()
+ {
+ // Arrange & Act
+ var cut = RenderComponent();
+
+ // Assert
+ cut.Markup.Should().Contain("도움말");
+ cut.Markup.Should().Contain("문서");
+ cut.Markup.Should().Contain("API");
+ }
+}