Skip to content

Commit 5129747

Browse files
spaarke-devclaude
andcommitted
fix: add comprehensive mock OBO service for testing
- Create MockOboSpeService with realistic mock responses - Update CustomWebAppFactory to use mock service when USE_FAKE_GRAPH=1 - Add detailed test logging to GitHub Actions workflow - This should resolve the remaining test failures in CI/CD 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 645c85b commit 5129747

3 files changed

Lines changed: 144 additions & 3 deletions

File tree

.github/workflows/deploy-to-azure.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ jobs:
4242
run: dotnet build --no-restore --configuration Release
4343

4444
- name: Test
45-
run: dotnet test --configuration Release --logger trx --collect:"XPlat Code Coverage" --verbosity normal
45+
run: dotnet test --configuration Release --logger "console;verbosity=detailed" --logger trx --collect:"XPlat Code Coverage" --verbosity normal
4646
env:
4747
USE_FAKE_GRAPH: 1
4848

tests/Spe.Bff.Api.Tests/CustomWebAppFactory.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Microsoft.AspNetCore.Hosting;
66
using Spe.Bff.Api.Tests.Mocks;
77
using Spe.Bff.Api.Infrastructure.Graph;
8+
using Services;
89

910
namespace Spe.Bff.Api.Tests;
1011

@@ -30,9 +31,15 @@ protected override void ConfigureWebHost(IWebHostBuilder builder)
3031
{
3132
if (Environment.GetEnvironmentVariable("USE_FAKE_GRAPH") == "1")
3233
{
33-
var d = services.SingleOrDefault(s => s.ServiceType == typeof(IGraphClientFactory));
34-
if (d != null) services.Remove(d);
34+
// Replace Graph client factory
35+
var graphFactory = services.SingleOrDefault(s => s.ServiceType == typeof(IGraphClientFactory));
36+
if (graphFactory != null) services.Remove(graphFactory);
3537
services.AddSingleton<IGraphClientFactory, FakeGraphClientFactory>();
38+
39+
// Replace OBO SPE service with mock
40+
var oboService = services.SingleOrDefault(s => s.ServiceType == typeof(IOboSpeService));
41+
if (oboService != null) services.Remove(oboService);
42+
services.AddSingleton<IOboSpeService, MockOboSpeService>();
3643
}
3744
});
3845
}
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
using Services;
2+
using Spe.Bff.Api.Models;
3+
using Microsoft.Graph.Models;
4+
5+
namespace Spe.Bff.Api.Tests.Mocks;
6+
7+
public class MockOboSpeService : IOboSpeService
8+
{
9+
public Task<UserInfoResponse?> GetUserInfoAsync(string userBearer, CancellationToken ct = default)
10+
{
11+
if (string.IsNullOrEmpty(userBearer) || userBearer == "invalid-token")
12+
return Task.FromResult<UserInfoResponse?>(null);
13+
14+
var userInfo = new UserInfoResponse
15+
{
16+
DisplayName = "Test User",
17+
UserPrincipalName = "test.user@test.com",
18+
Oid = "test-oid-123"
19+
};
20+
return Task.FromResult<UserInfoResponse?>(userInfo);
21+
}
22+
23+
public Task<UserCapabilitiesResponse?> GetUserCapabilitiesAsync(string userBearer, string containerId, CancellationToken ct = default)
24+
{
25+
if (string.IsNullOrEmpty(userBearer) || userBearer == "invalid-token")
26+
return Task.FromResult<UserCapabilitiesResponse?>(null);
27+
28+
var capabilities = new UserCapabilitiesResponse
29+
{
30+
CanRead = true,
31+
CanWrite = true,
32+
CanDelete = false,
33+
CanManage = false
34+
};
35+
return Task.FromResult<UserCapabilitiesResponse?>(capabilities);
36+
}
37+
38+
public Task<ListingResponse?> ListChildrenAsync(string userBearer, string id, ListingParameters parameters, CancellationToken ct = default)
39+
{
40+
if (string.IsNullOrEmpty(userBearer) || userBearer == "invalid-token")
41+
return Task.FromResult<ListingResponse?>(null);
42+
43+
var response = new ListingResponse
44+
{
45+
Items = new List<DriveItem>(),
46+
TotalCount = 0,
47+
HasNextPage = false,
48+
NextPageToken = null
49+
};
50+
return Task.FromResult<ListingResponse?>(response);
51+
}
52+
53+
public Task<DriveItem?> UploadSmallAsync(string userBearer, string id, string path, Stream content, CancellationToken ct = default)
54+
{
55+
if (string.IsNullOrEmpty(userBearer) || userBearer == "invalid-token")
56+
return Task.FromResult<DriveItem?>(null);
57+
58+
var item = new DriveItem
59+
{
60+
Id = "test-item-id",
61+
Name = Path.GetFileName(path),
62+
Size = content.Length
63+
};
64+
return Task.FromResult<DriveItem?>(item);
65+
}
66+
67+
public Task<UploadSession?> CreateUploadSessionAsync(string userBearer, string driveId, string path, ConflictBehavior behavior, CancellationToken ct = default)
68+
{
69+
if (string.IsNullOrEmpty(userBearer) || userBearer == "invalid-token")
70+
return Task.FromResult<UploadSession?>(null);
71+
72+
var session = new UploadSession
73+
{
74+
UploadUrl = "https://fake-upload-url.com/session-123"
75+
};
76+
return Task.FromResult<UploadSession?>(session);
77+
}
78+
79+
public Task<UploadChunkResult> UploadChunkAsync(string userBearer, string uploadUrl, string contentRange, byte[] chunkData, CancellationToken ct = default)
80+
{
81+
if (string.IsNullOrEmpty(userBearer) || userBearer == "invalid-token")
82+
{
83+
return Task.FromResult(new UploadChunkResult { StatusCode = 401 });
84+
}
85+
86+
// Simulate successful chunk upload
87+
var result = new UploadChunkResult
88+
{
89+
StatusCode = 202, // More chunks expected
90+
CompletedItem = null
91+
};
92+
return Task.FromResult(result);
93+
}
94+
95+
public Task<DriveItem?> UpdateItemAsync(string userBearer, string driveId, string itemId, UpdateFileRequest request, CancellationToken ct = default)
96+
{
97+
if (string.IsNullOrEmpty(userBearer) || userBearer == "invalid-token")
98+
return Task.FromResult<DriveItem?>(null);
99+
100+
var item = new DriveItem
101+
{
102+
Id = itemId,
103+
Name = request.Name ?? "updated-item",
104+
ParentReference = new ItemReference { Id = request.ParentReferenceId }
105+
};
106+
return Task.FromResult<DriveItem?>(item);
107+
}
108+
109+
public Task<FileContentResponse?> DownloadContentWithRangeAsync(string userBearer, string driveId, string itemId, RangeHeader? range, string? ifNoneMatch, CancellationToken ct = default)
110+
{
111+
if (string.IsNullOrEmpty(userBearer) || userBearer == "invalid-token")
112+
return Task.FromResult<FileContentResponse?>(null);
113+
114+
var content = new MemoryStream(System.Text.Encoding.UTF8.GetBytes("Mock file content"));
115+
var response = new FileContentResponse
116+
{
117+
Content = content,
118+
ContentType = "text/plain",
119+
ContentLength = content.Length,
120+
ETag = "mock-etag-123",
121+
IsRangeRequest = range != null,
122+
ContentRangeHeader = range != null ? $"bytes 0-{content.Length - 1}/{content.Length}" : null
123+
};
124+
return Task.FromResult<FileContentResponse?>(response);
125+
}
126+
127+
public Task<bool> DeleteItemAsync(string userBearer, string driveId, string itemId, CancellationToken ct = default)
128+
{
129+
if (string.IsNullOrEmpty(userBearer) || userBearer == "invalid-token")
130+
return Task.FromResult(false);
131+
132+
return Task.FromResult(true);
133+
}
134+
}

0 commit comments

Comments
 (0)