Skip to content

Commit e92f30d

Browse files
author
davidwei
committed
Refactor SearchService to use INoteRepository for note retrieval
1 parent 893a2bb commit e92f30d

File tree

2 files changed

+24
-28
lines changed

2 files changed

+24
-28
lines changed

src/HappyNotes.Services/SearchService.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using HappyNotes.Entities;
88
using HappyNotes.Models.Search;
99
using HappyNotes.Services.interfaces;
10+
using HappyNotes.Repositories.interfaces;
1011
using SqlSugar;
1112

1213
namespace HappyNotes.Services;
@@ -15,11 +16,13 @@ public class SearchService : ISearchService
1516
{
1617
private readonly IDatabaseClient _client;
1718
private readonly HttpClient _httpClient;
19+
private readonly INoteRepository _noteRepository;
1820

19-
public SearchService(IDatabaseClient client, HttpClient httpClient, ManticoreConnectionOptions options)
21+
public SearchService(IDatabaseClient client, HttpClient httpClient, ManticoreConnectionOptions options, INoteRepository noteRepository)
2022
{
2123
_client = client;
2224
_httpClient = httpClient;
25+
_noteRepository = noteRepository;
2326
_httpClient.BaseAddress = new Uri(options.HttpEndpoint);
2427
_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
2528
}
@@ -71,10 +74,7 @@ public SearchService(IDatabaseClient client, HttpClient httpClient, ManticoreCon
7174
if (pageNumber == 1 && long.TryParse(query, out long noteId))
7275
{
7376
// Check if this note ID belongs to the current user
74-
var notes = await _client.SqlQueryAsync<Note>(
75-
"SELECT Id, UserId FROM Note WHERE Id = @noteId",
76-
new { noteId });
77-
var note = notes.FirstOrDefault();
77+
var note = await _noteRepository.GetFirstOrDefaultAsync(n => n.Id == noteId);
7878

7979
if (note != null && note.UserId == userId)
8080
{

tests/HappyNotes.Services.Tests/SearchServiceTests.cs

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using HappyNotes.Common.Enums;
33
using HappyNotes.Entities;
44
using HappyNotes.Services.interfaces;
5+
using HappyNotes.Repositories.interfaces;
56
using Moq;
67
using Moq.Protected;
78
using SqlSugar;
@@ -12,12 +13,14 @@ namespace HappyNotes.Services.Tests;
1213
public class SearchServiceTests
1314
{
1415
private readonly Mock<IDatabaseClient> _mockDatabaseClient;
16+
private readonly Mock<INoteRepository> _mockNoteRepository;
1517
private readonly SearchService _searchService;
1618
private readonly Mock<HttpMessageHandler> _mockHandler;
1719

1820
public SearchServiceTests()
1921
{
2022
_mockDatabaseClient = new Mock<IDatabaseClient>();
23+
_mockNoteRepository = new Mock<INoteRepository>();
2124
_mockHandler = new Mock<HttpMessageHandler>();
2225
_mockHandler.Protected()
2326
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
@@ -28,14 +31,15 @@ public SearchServiceTests()
2831
});
2932
var httpClient = new HttpClient(_mockHandler.Object);
3033
var options = new ManticoreConnectionOptions { HttpEndpoint = "http://127.0.0.1:9308" };
31-
_searchService = new SearchService(_mockDatabaseClient.Object, httpClient, options);
34+
_searchService = new SearchService(_mockDatabaseClient.Object, httpClient, options, _mockNoteRepository.Object);
3235
}
3336

3437
[SetUp]
3538
public void Setup()
3639
{
3740
// Reset mock invocations before each test to avoid cross-test interference.
3841
_mockDatabaseClient.Reset();
42+
_mockNoteRepository.Reset();
3943
_mockHandler.Reset();
4044
_mockHandler.Protected()
4145
.Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.IsAny<HttpRequestMessage>(), ItExpr.IsAny<CancellationToken>())
@@ -315,11 +319,9 @@ public async Task GetNoteIdsByKeywordAsync_IntegerQuery_FirstPage_UserOwnsNote_P
315319
Content = new StringContent("{\"took\":0,\"timed_out\":false,\"hits\":{\"total\":2,\"hits\":[{\"_id\":456,\"_source\":{\"id\":456}},{\"_id\":789,\"_source\":{\"id\":789}}]}}")
316320
});
317321

318-
// Mock database query to return user's note
319-
_mockDatabaseClient.Setup(x => x.SqlQueryAsync<Note>(
320-
It.IsAny<string>(),
321-
It.IsAny<object>()))
322-
.ReturnsAsync(new List<Note> { new Note { Id = 123, UserId = 1 } });
322+
// Mock repository query to return user's note
323+
_mockNoteRepository.Setup(x => x.GetFirstOrDefaultAsync(It.IsAny<System.Linq.Expressions.Expression<System.Func<Note, bool>>>(), null))
324+
.ReturnsAsync(new Note { Id = 123, UserId = 1 });
323325

324326
// Act
325327
var result = await _searchService.GetNoteIdsByKeywordAsync(userId, query, pageNumber, pageSize);
@@ -349,11 +351,9 @@ public async Task GetNoteIdsByKeywordAsync_IntegerQuery_FirstPage_UserDoesNotOwn
349351
Content = new StringContent("{\"took\":0,\"timed_out\":false,\"hits\":{\"total\":2,\"hits\":[{\"_id\":456,\"_source\":{\"id\":456}},{\"_id\":789,\"_source\":{\"id\":789}}]}}")
350352
});
351353

352-
// Mock database query to return note owned by different user
353-
_mockDatabaseClient.Setup(x => x.SqlQueryAsync<Note>(
354-
It.IsAny<string>(),
355-
It.IsAny<object>()))
356-
.ReturnsAsync(new List<Note> { new Note { Id = 123, UserId = 2 } }); // Different user
354+
// Mock repository query to return note owned by different user
355+
_mockNoteRepository.Setup(x => x.GetFirstOrDefaultAsync(It.IsAny<System.Linq.Expressions.Expression<System.Func<Note, bool>>>(), null))
356+
.ReturnsAsync(new Note { Id = 123, UserId = 2 }); // Different user
357357

358358
// Act
359359
var result = await _searchService.GetNoteIdsByKeywordAsync(userId, query, pageNumber, pageSize);
@@ -390,7 +390,7 @@ public async Task GetNoteIdsByKeywordAsync_IntegerQuery_SecondPage_DoesNotPrepen
390390
Assert.That(result.Item1.Count, Is.EqualTo(2)); // Should remain 2 notes
391391
CollectionAssert.AreEqual(new List<long> { 456, 789 }, result.Item1);
392392
// Verify database was not called since it's not first page
393-
_mockDatabaseClient.Verify(x => x.SqlQueryAsync<Note>(It.IsAny<string>(), It.IsAny<object>()), Times.Never);
393+
_mockNoteRepository.Verify(x => x.GetFirstOrDefaultAsync(It.IsAny<System.Linq.Expressions.Expression<System.Func<Note, bool>>>(), null), Times.Never);
394394
}
395395

396396
[Test]
@@ -411,11 +411,9 @@ public async Task GetNoteIdsByKeywordAsync_IntegerQuery_NoteNotFound_DoesNotPrep
411411
Content = new StringContent("{\"took\":0,\"timed_out\":false,\"hits\":{\"total\":2,\"hits\":[{\"_id\":456,\"_source\":{\"id\":456}},{\"_id\":789,\"_source\":{\"id\":789}}]}}")
412412
});
413413

414-
// Mock database query to return empty list (note not found)
415-
_mockDatabaseClient.Setup(x => x.SqlQueryAsync<Note>(
416-
It.IsAny<string>(),
417-
It.IsAny<object>()))
418-
.ReturnsAsync(new List<Note>());
414+
// Mock repository query to return null (note not found)
415+
_mockNoteRepository.Setup(x => x.GetFirstOrDefaultAsync(It.IsAny<System.Linq.Expressions.Expression<System.Func<Note, bool>>>(), null))
416+
.ReturnsAsync((Note?)null);
419417

420418
// Act
421419
var result = await _searchService.GetNoteIdsByKeywordAsync(userId, query, pageNumber, pageSize);
@@ -444,11 +442,9 @@ public async Task GetNoteIdsByKeywordAsync_IntegerQuery_FirstPage_NoteAlreadyInR
444442
Content = new StringContent("{\"took\":0,\"timed_out\":false,\"hits\":{\"total\":3,\"hits\":[{\"_id\":456,\"_source\":{\"id\":456}},{\"_id\":123,\"_source\":{\"id\":123}},{\"_id\":789,\"_source\":{\"id\":789}}]}}")
445443
});
446444

447-
// Mock database query to return user's note
448-
_mockDatabaseClient.Setup(x => x.SqlQueryAsync<Note>(
449-
It.IsAny<string>(),
450-
It.IsAny<object>()))
451-
.ReturnsAsync(new List<Note> { new Note { Id = 123, UserId = 1 } });
445+
// Mock repository query to return user's note
446+
_mockNoteRepository.Setup(x => x.GetFirstOrDefaultAsync(It.IsAny<System.Linq.Expressions.Expression<System.Func<Note, bool>>>(), null))
447+
.ReturnsAsync(new Note { Id = 123, UserId = 1 });
452448

453449
// Act
454450
var result = await _searchService.GetNoteIdsByKeywordAsync(userId, query, pageNumber, pageSize);
@@ -486,6 +482,6 @@ public async Task GetNoteIdsByKeywordAsync_NonIntegerQuery_DoesNotPrepend()
486482
Assert.That(result.Item1.Count, Is.EqualTo(2)); // Should remain 2 notes
487483
CollectionAssert.AreEqual(new List<long> { 456, 789 }, result.Item1);
488484
// Verify database was not called since query is not an integer
489-
_mockDatabaseClient.Verify(x => x.SqlQueryAsync<Note>(It.IsAny<string>(), It.IsAny<object>()), Times.Never);
485+
_mockNoteRepository.Verify(x => x.GetFirstOrDefaultAsync(It.IsAny<System.Linq.Expressions.Expression<System.Func<Note, bool>>>(), null), Times.Never);
490486
}
491487
}

0 commit comments

Comments
 (0)