Skip to content

Commit 68277f3

Browse files
committed
test(backend/Application.Functions): add unit tests for task functions
Implemented unit tests for methods in TaskFunctions. These tests cover various scenarios including happy paths, validation errors, and business rule violations. Modified files (8): - CreateTasksTests.cs: Added tests for creating tasks - DeleteTasksTests.cs: Added tests for deleting tasks - GetTasksDetailsTests.cs: Added tests for getting task details - GetTasksSummaryTests.cs: Added tests for getting task summary - ListTasksTests.cs: Added tests for listing tasks with and without filters - UpdateTaskTests.cs: Added tests for updating task status and priority - GlobalUsings.cs: Added global using directives for test libraries This enhances test coverage and ensures the correctness of task management functionalities.
1 parent 5ae4e6d commit 68277f3

8 files changed

Lines changed: 1526 additions & 0 deletions

File tree

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
using Microsoft.Extensions.Logging.Abstractions;
2+
using TaskAgent.Application.Constants;
3+
using TaskAgent.Application.Functions;
4+
using TaskAgent.Application.Interfaces;
5+
using TaskAgent.Application.Telemetry;
6+
using TaskAgent.Domain.Entities;
7+
using TaskAgent.Domain.Enums;
8+
9+
namespace TaskAgent.Application.UnitTests.Functions;
10+
11+
/// <summary>
12+
/// Unit tests for TaskFunctions.CreateTaskAsync following AAA pattern
13+
/// </summary>
14+
public class CreateTaskTests
15+
{
16+
private readonly ITaskRepository _mockRepository;
17+
private readonly TaskFunctions _taskFunctions;
18+
19+
public CreateTaskTests()
20+
{
21+
_mockRepository = Substitute.For<ITaskRepository>();
22+
_taskFunctions = CreateTaskFunctions(_mockRepository);
23+
}
24+
25+
#region Happy Path Tests
26+
27+
[Fact]
28+
public async Task CreateTaskAsync_WithValidData_ReturnsSuccessMessage()
29+
{
30+
// Arrange
31+
const string title = "Test Task";
32+
const string description = "Test Description";
33+
const string priority = "Medium";
34+
35+
_mockRepository.AddAsync(Arg.Any<TaskItem>())
36+
.Returns(callInfo => callInfo.Arg<TaskItem>());
37+
_mockRepository.SaveChangesAsync().Returns(1);
38+
39+
// Act
40+
string result = await _taskFunctions.CreateTaskAsync(title, description, priority);
41+
42+
// Assert
43+
result.Should().Contain(SuccessMessages.TASK_CREATED_SUCCESS);
44+
result.Should().Contain(title);
45+
result.Should().Contain(description);
46+
result.Should().Contain("Medium");
47+
}
48+
49+
[Fact]
50+
public async Task CreateTaskAsync_WithValidData_PersistsToRepository()
51+
{
52+
// Arrange
53+
const string title = "Test Task";
54+
const string description = "Test Description";
55+
const string priority = "High";
56+
57+
_mockRepository.AddAsync(Arg.Any<TaskItem>())
58+
.Returns(callInfo => callInfo.Arg<TaskItem>());
59+
_mockRepository.SaveChangesAsync().Returns(1);
60+
61+
// Act
62+
await _taskFunctions.CreateTaskAsync(title, description, priority);
63+
64+
// Assert
65+
await _mockRepository.Received(1).AddAsync(Arg.Is<TaskItem>(t =>
66+
t.Title == title &&
67+
t.Description == description &&
68+
t.Priority == TaskPriority.High));
69+
await _mockRepository.Received(1).SaveChangesAsync();
70+
}
71+
72+
#endregion
73+
74+
#region Validation Tests
75+
76+
[Fact]
77+
public async Task CreateTaskAsync_WithEmptyTitle_ReturnsErrorMessage()
78+
{
79+
// Arrange
80+
const string emptyTitle = "";
81+
const string description = "Test Description";
82+
const string priority = "Medium";
83+
84+
// Act
85+
string result = await _taskFunctions.CreateTaskAsync(emptyTitle, description, priority);
86+
87+
// Assert
88+
result.Should().Be(ErrorMessages.TASK_TITLE_EMPTY);
89+
}
90+
91+
[Fact]
92+
public async Task CreateTaskAsync_WithWhitespaceTitle_ReturnsErrorMessage()
93+
{
94+
// Arrange
95+
const string whitespaceTitle = " ";
96+
const string description = "Test Description";
97+
const string priority = "Medium";
98+
99+
// Act
100+
string result = await _taskFunctions.CreateTaskAsync(whitespaceTitle, description, priority);
101+
102+
// Assert
103+
result.Should().Be(ErrorMessages.TASK_TITLE_EMPTY);
104+
}
105+
106+
[Fact]
107+
public async Task CreateTaskAsync_WithInvalidPriority_ReturnsErrorMessage()
108+
{
109+
// Arrange
110+
const string title = "Test Task";
111+
const string description = "Test Description";
112+
const string invalidPriority = "VeryHigh";
113+
114+
// Act
115+
string result = await _taskFunctions.CreateTaskAsync(title, description, invalidPriority);
116+
117+
// Assert
118+
result.Should().Contain("Invalid priority");
119+
result.Should().Contain(invalidPriority);
120+
}
121+
122+
[Fact]
123+
public async Task CreateTaskAsync_WithNullDescription_UsesEmptyString()
124+
{
125+
// Arrange
126+
const string title = "Test Task";
127+
string? nullDescription = null;
128+
const string priority = "Low";
129+
130+
_mockRepository.AddAsync(Arg.Any<TaskItem>())
131+
.Returns(callInfo => callInfo.Arg<TaskItem>());
132+
_mockRepository.SaveChangesAsync().Returns(1);
133+
134+
// Act
135+
string result = await _taskFunctions.CreateTaskAsync(title, nullDescription!, priority);
136+
137+
// Assert
138+
result.Should().Contain(SuccessMessages.TASK_CREATED_SUCCESS);
139+
await _mockRepository.Received(1).AddAsync(Arg.Is<TaskItem>(t =>
140+
t.Description == string.Empty));
141+
}
142+
143+
#endregion
144+
145+
#region Priority Parsing Tests
146+
147+
[Theory]
148+
[InlineData("Low", TaskPriority.Low)]
149+
[InlineData("low", TaskPriority.Low)]
150+
[InlineData("LOW", TaskPriority.Low)]
151+
[InlineData("Medium", TaskPriority.Medium)]
152+
[InlineData("medium", TaskPriority.Medium)]
153+
[InlineData("MEDIUM", TaskPriority.Medium)]
154+
[InlineData("High", TaskPriority.High)]
155+
[InlineData("high", TaskPriority.High)]
156+
[InlineData("HIGH", TaskPriority.High)]
157+
public async Task CreateTaskAsync_ParsesPriorityCaseInsensitively(string input, TaskPriority expected)
158+
{
159+
// Arrange
160+
const string title = "Test Task";
161+
const string description = "Test Description";
162+
163+
_mockRepository.AddAsync(Arg.Any<TaskItem>())
164+
.Returns(callInfo => callInfo.Arg<TaskItem>());
165+
_mockRepository.SaveChangesAsync().Returns(1);
166+
167+
// Act
168+
string result = await _taskFunctions.CreateTaskAsync(title, description, input);
169+
170+
// Assert
171+
result.Should().Contain(SuccessMessages.TASK_CREATED_SUCCESS);
172+
await _mockRepository.Received(1).AddAsync(Arg.Is<TaskItem>(t =>
173+
t.Priority == expected));
174+
}
175+
176+
#endregion
177+
178+
#region Default Priority Test
179+
180+
[Fact]
181+
public async Task CreateTaskAsync_WithDefaultPriority_UsesMedium()
182+
{
183+
// Arrange
184+
const string title = "Test Task";
185+
const string description = "Test Description";
186+
187+
_mockRepository.AddAsync(Arg.Any<TaskItem>())
188+
.Returns(callInfo => callInfo.Arg<TaskItem>());
189+
_mockRepository.SaveChangesAsync().Returns(1);
190+
191+
// Act
192+
string result = await _taskFunctions.CreateTaskAsync(title, description);
193+
194+
// Assert
195+
result.Should().Contain(SuccessMessages.TASK_CREATED_SUCCESS);
196+
result.Should().Contain("Medium");
197+
}
198+
199+
#endregion
200+
201+
#region Helper Methods
202+
203+
private static TaskFunctions CreateTaskFunctions(ITaskRepository mockRepository)
204+
{
205+
var services = new ServiceCollection();
206+
services.AddSingleton(mockRepository);
207+
208+
ServiceProvider serviceProvider = services.BuildServiceProvider();
209+
var metrics = new AgentMetrics();
210+
NullLogger<TaskFunctions> logger = NullLogger<TaskFunctions>.Instance;
211+
212+
return new TaskFunctions(serviceProvider, metrics, logger);
213+
}
214+
215+
#endregion
216+
}

0 commit comments

Comments
 (0)