-
Notifications
You must be signed in to change notification settings - Fork 58
Expand file tree
/
Copy pathBaseNuGetProjectManagerIntegrationTests.cs
More file actions
257 lines (226 loc) · 12.4 KB
/
Copy pathBaseNuGetProjectManagerIntegrationTests.cs
File metadata and controls
257 lines (226 loc) · 12.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
namespace Microsoft.CST.OpenSource.Tests.ProjectManagerTests
{
using Microsoft.CST.OpenSource;
using Microsoft.CST.OpenSource.PackageManagers;
using NSubstitute;
using oss;
using PackageUrl;
using RichardSzalay.MockHttp;
using System;
using System.Net;
using System.Net.Http;
using Xunit;
/// <summary>
/// Tests for BaseNuGetProjectManager factory methods with mocked HTTP responses.
/// These tests verify the manager creation logic without reaching out to the public internet.
///
/// This refactoring uses NSubstitute for mocking IHttpClientFactory and MockHttp for HTTP responses,
/// following implementation best practices to avoid spurious failures from live API calls in CI/CD pipelines.
/// </summary>
public class BaseNuGetProjectManagerIntegrationTests
{
/// <summary>
/// Test to verify that the V2 API endpoint detection works correctly.
/// Uses NSubstitute for mocking the IHttpClientFactory and MockHttp for HTTP responses.
/// Validates that when a repository URL ends with /api/v2, a NuGetV2ProjectManager is created.
/// </summary>
[Theory]
[InlineData("pkg:nuget/Newtonsoft.Json@12.0.3?repository_url=https://www.nuget.org/api/v2", typeof(NuGetV2ProjectManager))]
[InlineData("pkg:nuget/Microsoft.Extensions.Logging@8.0.0?repository_url=https://www.nuget.org/api/v2", typeof(NuGetV2ProjectManager))]
public void Create_WithV2RepositoryUrl_CreatesCorrectManagerType(string purlString, Type expectedType)
{
// Arrange
PackageURL packageUrl = new(purlString);
// Create a mock HTTP client factory using NSubstitute
// This demonstrates the use of NSubstitute for mocking as requested
IHttpClientFactory mockHttpClientFactory = Substitute.For<IHttpClientFactory>();
// Set up MockHttp to provide mocked HTTP responses
MockHttpMessageHandler mockHttp = new();
// Mock any potential HTTP calls with generic responses
mockHttp
.When(HttpMethod.Get, "*")
.Respond(HttpStatusCode.OK);
HttpClient httpClient = mockHttp.ToHttpClient();
mockHttpClientFactory.CreateClient(Arg.Any<string>()).Returns(httpClient);
// Act
BaseNuGetProjectManager manager = BaseNuGetProjectManager.Create(".", mockHttpClientFactory, TimeSpan.FromSeconds(30), packageUrl);
// Assert - Verify the correct manager type is created based on repository URL
Assert.IsType(expectedType, manager);
}
/// <summary>
/// Test to verify that PowerShell Gallery V2 endpoint detection works correctly.
/// Uses NSubstitute for mocking and demonstrates implementation best practices.
/// Validates backward compatibility with PowerShell Gallery's V2 API.
/// </summary>
[Theory]
[InlineData("pkg:nuget/PSReadLine@2.0.0?repository_url=https://www.powershellgallery.com/api/v2", typeof(NuGetV2ProjectManager))]
[InlineData("pkg:nuget/Az.Accounts@4.0.0?repository_url=https://www.powershellgallery.com/api/v2", typeof(NuGetV2ProjectManager))]
public void Create_WithPowerShellGalleryV2Url_CreatesCorrectManagerType(string purlString, Type expectedType)
{
// Arrange
PackageURL packageUrl = new(purlString);
// Create a mock HTTP client factory using NSubstitute
IHttpClientFactory mockHttpClientFactory = Substitute.For<IHttpClientFactory>();
// Set up MockHttp to provide mocked HTTP responses
MockHttpMessageHandler mockHttp = new();
// Mock the FindPackagesById endpoint with realistic V2 API XML response
mockHttp
.When(HttpMethod.Get, "https://www.powershellgallery.com/api/v2/FindPackagesById*")
.Respond(HttpStatusCode.OK, "application/xml", Resources.psreadline_xml);
// Mock the package download endpoint
mockHttp
.When(HttpMethod.Get, "https://www.powershellgallery.com/api/v2/package/*")
.Respond(HttpStatusCode.OK);
// Mock any other potential calls
mockHttp
.When(HttpMethod.Get, "*")
.Respond(HttpStatusCode.OK);
HttpClient httpClient = mockHttp.ToHttpClient();
mockHttpClientFactory.CreateClient(Arg.Any<string>()).Returns(httpClient);
// Act
BaseNuGetProjectManager manager = BaseNuGetProjectManager.Create(".", mockHttpClientFactory, TimeSpan.FromSeconds(30), packageUrl);
// Assert - Verify the correct manager type is created
Assert.IsType(expectedType, manager);
}
/// <summary>
/// Test to verify that NuGet V3 API detection works correctly (default when no V2 URL is present).
/// Uses NSubstitute for mocking the IHttpClientFactory and MockHttp for V3 API responses.
/// Validates that packages without a repository URL qualifier default to V3 API.
/// </summary>
[Theory]
[InlineData("pkg:nuget/Newtonsoft.Json@13.0.1", typeof(NuGetProjectManager))]
[InlineData("pkg:nuget/Microsoft.Extensions.Logging@8.0.0", typeof(NuGetProjectManager))]
[InlineData("pkg:nuget/Newtonsoft.Json", typeof(NuGetProjectManager))]
public void Create_WithV3OrDefaultUrl_CreatesCorrectManagerType(string purlString, Type expectedType)
{
// Arrange
PackageURL packageUrl = new(purlString);
// Create a mock HTTP client factory using NSubstitute
IHttpClientFactory mockHttpClientFactory = Substitute.For<IHttpClientFactory>();
// Set up MockHttp to mock HTTP responses for V3 API
MockHttpMessageHandler mockHttp = new();
// Mock the service index endpoint - this is the first call V3 managers make
mockHttp
.When(HttpMethod.Get, "https://api.nuget.org/v3/index.json")
.Respond(HttpStatusCode.OK, "application/json", Resources.nuget_registration_json);
// Mock registration endpoints with realistic V3 API responses
mockHttp
.When(HttpMethod.Get, "https://api.nuget.org/v3/registration5-gz-semver2/newtonsoft.json/index.json")
.Respond(HttpStatusCode.OK, "application/json", GetMockedNewtonsoftJsonV3RegistrationResponse());
mockHttp
.When(HttpMethod.Get, "https://api.nuget.org/v3/registration5-gz-semver2/microsoft.extensions.logging/index.json")
.Respond(HttpStatusCode.OK, "application/json", GetMockedMicrosoftExtensionsLoggingV3Response());
// Mock package content endpoints
mockHttp
.When(HttpMethod.Get, "https://api.nuget.org/v3-flatcontainer/*.nupkg")
.Respond(HttpStatusCode.OK);
mockHttp
.When(HttpMethod.Get, "https://api.nuget.org/v3-flatcontainer/*.nuspec")
.Respond(HttpStatusCode.OK);
// Mock any other potential calls with a generic OK response
mockHttp
.When(HttpMethod.Get, "*")
.Respond(HttpStatusCode.OK);
HttpClient httpClient = mockHttp.ToHttpClient();
mockHttpClientFactory.CreateClient(Arg.Any<string>()).Returns(httpClient);
// Act
BaseNuGetProjectManager manager = BaseNuGetProjectManager.Create(".", mockHttpClientFactory, TimeSpan.FromSeconds(30), packageUrl);
// Assert - Verify the correct manager type is created (should be V3/NuGetProjectManager)
Assert.IsType(expectedType, manager);
}
/// <summary>
/// Gets a mocked V3 API registration response for Newtonsoft.Json package.
/// This represents the expected response from the NuGet V3 API registration endpoint.
/// Based on actual API responses but simplified for testing purposes.
/// </summary>
private static string GetMockedNewtonsoftJsonV3RegistrationResponse()
{
return @"{
""@id"": ""https://api.nuget.org/v3/registration5-gz-semver2/newtonsoft.json/index.json"",
""@type"": [""catalog:CatalogRoot"", ""PackageRegistration""],
""commitId"": ""b6c4f1b2-3e4a-4d5c-9f8e-7a6b5c4d3e2f"",
""commitTimeStamp"": ""2024-01-01T00:00:00.0000000Z"",
""count"": 1,
""items"": [
{
""@id"": ""https://api.nuget.org/v3/registration5-gz-semver2/newtonsoft.json/index.json#page/13.0.1/13.0.1"",
""@type"": ""catalog:CatalogPage"",
""commitId"": ""b6c4f1b2-3e4a-4d5c-9f8e-7a6b5c4d3e2f"",
""commitTimeStamp"": ""2024-01-01T00:00:00.0000000Z"",
""count"": 1,
""items"": [
{
""@id"": ""https://api.nuget.org/v3/registration5-gz-semver2/newtonsoft.json/13.0.1.json"",
""@type"": ""Package"",
""commitId"": ""b6c4f1b2-3e4a-4d5c-9f8e-7a6b5c4d3e2f"",
""commitTimeStamp"": ""2024-01-01T00:00:00.0000000Z"",
""catalogEntry"": {
""@id"": ""https://api.nuget.org/v3/catalog0/data/2021.02.20.09.34.30/newtonsoft.json.13.0.1.json"",
""@type"": ""PackageDetails"",
""authors"": ""James Newton-King"",
""description"": ""Json.NET is a popular high-performance JSON framework for .NET"",
""id"": ""Newtonsoft.Json"",
""version"": ""13.0.1"",
""listed"": true,
""published"": ""2021-02-20T09:34:30.123+00:00""
},
""packageContent"": ""https://api.nuget.org/v3-flatcontainer/newtonsoft.json/13.0.1/newtonsoft.json.13.0.1.nupkg"",
""registration"": ""https://api.nuget.org/v3/registration5-gz-semver2/newtonsoft.json/index.json""
}
],
""parent"": ""https://api.nuget.org/v3/registration5-gz-semver2/newtonsoft.json/index.json"",
""lower"": ""13.0.1"",
""upper"": ""13.0.1""
}
]
}";
}
/// <summary>
/// Gets a mocked V3 API registration response for Microsoft.Extensions.Logging package.
/// This represents the expected response from the NuGet V3 API registration endpoint.
/// </summary>
private static string GetMockedMicrosoftExtensionsLoggingV3Response()
{
return @"{
""@id"": ""https://api.nuget.org/v3/registration5-gz-semver2/microsoft.extensions.logging/index.json"",
""@type"": [""catalog:CatalogRoot"", ""PackageRegistration""],
""commitId"": ""a1b2c3d4-5e6f-7g8h-9i0j-k1l2m3n4o5p6"",
""commitTimeStamp"": ""2024-01-01T00:00:00.0000000Z"",
""count"": 1,
""items"": [
{
""@id"": ""https://api.nuget.org/v3/registration5-gz-semver2/microsoft.extensions.logging/index.json#page/8.0.0/8.0.0"",
""@type"": ""catalog:CatalogPage"",
""commitId"": ""a1b2c3d4-5e6f-7g8h-9i0j-k1l2m3n4o5p6"",
""commitTimeStamp"": ""2024-01-01T00:00:00.0000000Z"",
""count"": 1,
""items"": [
{
""@id"": ""https://api.nuget.org/v3/registration5-gz-semver2/microsoft.extensions.logging/8.0.0.json"",
""@type"": ""Package"",
""commitId"": ""a1b2c3d4-5e6f-7g8h-9i0j-k1l2m3n4o5p6"",
""commitTimeStamp"": ""2024-01-01T00:00:00.0000000Z"",
""catalogEntry"": {
""@id"": ""https://api.nuget.org/v3/catalog0/data/2023.11.14.21.43.10/microsoft.extensions.logging.8.0.0.json"",
""@type"": ""PackageDetails"",
""authors"": ""Microsoft"",
""description"": ""Logging infrastructure default implementation for Microsoft.Extensions.Logging."",
""id"": ""Microsoft.Extensions.Logging"",
""version"": ""8.0.0"",
""listed"": true,
""published"": ""2023-11-14T21:43:10.000+00:00""
},
""packageContent"": ""https://api.nuget.org/v3-flatcontainer/microsoft.extensions.logging/8.0.0/microsoft.extensions.logging.8.0.0.nupkg"",
""registration"": ""https://api.nuget.org/v3/registration5-gz-semver2/microsoft.extensions.logging/index.json""
}
],
""parent"": ""https://api.nuget.org/v3/registration5-gz-semver2/microsoft.extensions.logging/index.json"",
""lower"": ""8.0.0"",
""upper"": ""8.0.0""
}
]
}";
}
}
}