Skip to content

Commit 1d07e2a

Browse files
fjakobsclaude
andcommitted
Improve test mocks to verify specific API paths and methods
Instead of using `anything()` matchers for all parameters, now use `objectContaining()` to verify that tests are calling the correct API endpoints with the correct HTTP methods. This ensures tests validate actual API contract behavior: - GET /api/2.1/clusters/get - for cluster status - GET /api/2.0/clusters/list - for listing clusters - GET /api/2.0/permissions/clusters/{id} - for permissions - POST /api/2.1/clusters/delete - for stopping/terminating clusters This provides better test coverage and catches potential regressions in API endpoint usage. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent b2b1021 commit 1d07e2a

5 files changed

Lines changed: 190 additions & 27 deletions

File tree

packages/databricks-vscode/src/cluster/ClusterLoader.test.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ import {
66
WorkspaceClient,
77
} from "@databricks/sdk-experimental";
88
import assert from "assert";
9-
import {anything, instance, mock, spy, when} from "ts-mockito";
9+
import {
10+
anything,
11+
instance,
12+
mock,
13+
objectContaining,
14+
spy,
15+
when,
16+
} from "ts-mockito";
1017
import {ConnectionManager} from "../configuration/ConnectionManager";
1118
import {ClusterLoader} from "./ClusterLoader";
1219

@@ -101,17 +108,23 @@ describe(__filename, () => {
101108

102109
when<compute.ListClustersResponse>(
103110
mockedApiClient.request(
104-
anything(),
111+
objectContaining({
112+
path: "/api/2.0/clusters/list",
113+
method: "GET",
114+
}),
105115
anything()
106116
) as Promise<compute.ListClustersResponse>
107117
).thenResolve(mockListClustersResponse);
108118
when(mockedConnectionManager.workspaceClient).thenReturn(
109119
instance(mockedWorkspaceClient)
110120
);
111-
for (const [, perms] of mockClusterPermissions.entries()) {
121+
for (const [clusterId, perms] of mockClusterPermissions.entries()) {
112122
when<iam.ObjectPermissions>(
113123
mockedApiClient.request(
114-
anything(),
124+
objectContaining({
125+
path: `/api/2.0/permissions/clusters/${clusterId}`,
126+
method: "GET",
127+
}),
115128
anything()
116129
) as Promise<iam.ObjectPermissions>
117130
).thenResolve(perms);

packages/databricks-vscode/src/cluster/ClusterManager.test.ts

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,15 @@ import {
99
} from "@databricks/sdk-experimental";
1010
import {Cluster} from "../sdk-extensions";
1111
import {ClusterFixtures} from "../sdk-extensions/test";
12-
import {anything, instance, mock, resetCalls, verify, when} from "ts-mockito";
12+
import {
13+
anything,
14+
instance,
15+
mock,
16+
objectContaining,
17+
resetCalls,
18+
verify,
19+
when,
20+
} from "ts-mockito";
1321
import assert from "assert";
1422

1523
describe(__filename, async () => {
@@ -20,7 +28,15 @@ describe(__filename, async () => {
2028
beforeEach(async () => {
2129
({testClusterDetails} = await ClusterFixtures.getMockTestCluster());
2230
mockedClient = mock(ApiClient);
23-
when(mockedClient.request(anything(), anything())).thenResolve({
31+
when(
32+
mockedClient.request(
33+
objectContaining({
34+
path: "/api/2.1/clusters/get",
35+
method: "GET",
36+
}),
37+
anything()
38+
)
39+
).thenResolve({
2440
...testClusterDetails,
2541
state: "RUNNING",
2642
});
@@ -37,7 +53,15 @@ describe(__filename, async () => {
3753
});
3854

3955
it("should start a cluster with progress", async () => {
40-
when(mockedClient.request(anything(), anything())).thenResolve(
56+
when(
57+
mockedClient.request(
58+
objectContaining({
59+
path: "/api/2.1/clusters/get",
60+
method: "GET",
61+
}),
62+
anything()
63+
)
64+
).thenResolve(
4165
{
4266
...testClusterDetails,
4367
state: "TERMINATED",

packages/databricks-vscode/src/cluster/ClusterModel.test.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
/* eslint-disable @typescript-eslint/naming-convention */
22

33
import assert from "assert";
4-
import {mock, when, anything, instance, spy} from "ts-mockito";
4+
import {
5+
mock,
6+
when,
7+
anything,
8+
instance,
9+
spy,
10+
objectContaining,
11+
} from "ts-mockito";
512
import {
613
ApiClient,
714
WorkspaceClient,
@@ -48,7 +55,10 @@ describe(__filename, () => {
4855

4956
when<compute.ListClustersResponse>(
5057
mockedApiClient.request(
51-
anything(),
58+
objectContaining({
59+
path: "/api/2.0/clusters/list",
60+
method: "GET",
61+
}),
5262
anything()
5363
) as Promise<compute.ListClustersResponse>
5464
).thenResolve(mockListClustersResponse);

packages/databricks-vscode/src/sdk-extensions/Cluster.test.ts

Lines changed: 117 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,14 @@ import {
88
} from "@databricks/sdk-experimental";
99
import {Cluster} from "./Cluster";
1010
import * as assert from "node:assert";
11-
import {mock, when, instance, verify, anything} from "ts-mockito";
11+
import {
12+
mock,
13+
when,
14+
instance,
15+
verify,
16+
anything,
17+
objectContaining,
18+
} from "ts-mockito";
1219
import {getMockTestCluster} from "./test/ClusterFixtures";
1320
import {TokenFixture} from "./test/TokenFixtures";
1421
import FakeTimers from "@sinonjs/fake-timers";
@@ -33,7 +40,15 @@ describe(__filename, function () {
3340
});
3441

3542
it("calling start on a non terminated state should not throw an error", async () => {
36-
when(mockedClient.request(anything(), anything())).thenResolve(
43+
when(
44+
mockedClient.request(
45+
objectContaining({
46+
path: "/api/2.1/clusters/get",
47+
method: "GET",
48+
}),
49+
anything()
50+
)
51+
).thenResolve(
3752
{
3853
...testClusterDetails,
3954
state: "PENDING",
@@ -68,13 +83,37 @@ describe(__filename, function () {
6883
await startPromise;
6984
assert.equal(mockedCluster.state, "RUNNING");
7085

71-
verify(mockedClient.request(anything(), anything())).times(6);
72-
73-
verify(mockedClient.request(anything(), anything())).never();
86+
verify(
87+
mockedClient.request(
88+
objectContaining({
89+
path: "/api/2.1/clusters/get",
90+
method: "GET",
91+
}),
92+
anything()
93+
)
94+
).times(6);
95+
96+
verify(
97+
mockedClient.request(
98+
objectContaining({
99+
path: "/api/2.1/clusters/get",
100+
method: "GET",
101+
}),
102+
anything()
103+
)
104+
).never();
74105
});
75106

76107
it("should terminate cluster", async () => {
77-
when(mockedClient.request(anything(), anything())).thenResolve(
108+
when(
109+
mockedClient.request(
110+
objectContaining({
111+
path: "/api/2.1/clusters/get",
112+
method: "GET",
113+
}),
114+
anything()
115+
)
116+
).thenResolve(
78117
{
79118
...testClusterDetails,
80119
state: "RUNNING",
@@ -89,7 +128,15 @@ describe(__filename, function () {
89128
}
90129
);
91130

92-
when(mockedClient.request(anything(), anything())).thenResolve({});
131+
when(
132+
mockedClient.request(
133+
objectContaining({
134+
path: "/api/2.1/clusters/delete",
135+
method: "POST",
136+
}),
137+
anything()
138+
)
139+
).thenResolve({});
93140

94141
assert.equal(mockedCluster.state, "RUNNING");
95142

@@ -99,13 +146,37 @@ describe(__filename, function () {
99146

100147
assert.equal(mockedCluster.state, "TERMINATED");
101148

102-
verify(mockedClient.request(anything(), anything())).times(3);
103-
104-
verify(mockedClient.request(anything(), anything())).once();
149+
verify(
150+
mockedClient.request(
151+
objectContaining({
152+
path: "/api/2.1/clusters/get",
153+
method: "GET",
154+
}),
155+
anything()
156+
)
157+
).times(3);
158+
159+
verify(
160+
mockedClient.request(
161+
objectContaining({
162+
path: "/api/2.1/clusters/delete",
163+
method: "POST",
164+
}),
165+
anything()
166+
)
167+
).once();
105168
});
106169

107170
it("should terminate non running clusters", async () => {
108-
when(mockedClient.request(anything(), anything())).thenResolve(
171+
when(
172+
mockedClient.request(
173+
objectContaining({
174+
path: "/api/2.1/clusters/get",
175+
method: "GET",
176+
}),
177+
anything()
178+
)
179+
).thenResolve(
109180
{
110181
...testClusterDetails,
111182
state: "PENDING",
@@ -129,22 +200,52 @@ describe(__filename, function () {
129200

130201
assert.equal(mockedCluster.state, "TERMINATED");
131202

132-
verify(mockedClient.request(anything(), anything())).times(3);
133-
134-
verify(mockedClient.request(anything(), anything())).once();
203+
verify(
204+
mockedClient.request(
205+
objectContaining({
206+
path: "/api/2.1/clusters/get",
207+
method: "GET",
208+
}),
209+
anything()
210+
)
211+
).times(3);
212+
213+
verify(
214+
mockedClient.request(
215+
objectContaining({
216+
path: "/api/2.1/clusters/delete",
217+
method: "POST",
218+
}),
219+
anything()
220+
)
221+
).once();
135222
});
136223

137224
it("should cancel cluster start", async () => {
138225
const whenMockGetCluster = when(
139-
mockedClient.request(anything(), anything())
226+
mockedClient.request(
227+
objectContaining({
228+
path: "/api/2.1/clusters/get",
229+
method: "GET",
230+
}),
231+
anything()
232+
)
140233
);
141234

142235
whenMockGetCluster.thenResolve({
143236
...testClusterDetails,
144237
state: "PENDING",
145238
});
146239

147-
when(mockedClient.request(anything(), anything())).thenCall(() => {
240+
when(
241+
mockedClient.request(
242+
objectContaining({
243+
path: "/api/2.1/clusters/delete",
244+
method: "POST",
245+
}),
246+
anything()
247+
)
248+
).thenCall(() => {
148249
whenMockGetCluster.thenResolve(
149250
{
150251
...testClusterDetails,

packages/databricks-vscode/src/sdk-extensions/test/ClusterFixtures.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
/* eslint-disable @typescript-eslint/naming-convention */
22

33
import {Cluster} from "../Cluster";
4-
import {mock, when, resetCalls, instance, anything} from "ts-mockito";
4+
import {
5+
mock,
6+
when,
7+
resetCalls,
8+
instance,
9+
anything,
10+
objectContaining,
11+
} from "ts-mockito";
512
import {compute, ApiClient} from "@databricks/sdk-experimental";
613

714
const testClusterDetails: compute.ClusterDetails = {
@@ -11,7 +18,15 @@ const testClusterDetails: compute.ClusterDetails = {
1118

1219
export async function getMockTestCluster() {
1320
const mockedClient = mock(ApiClient);
14-
when(mockedClient.request(anything(), anything())).thenResolve({
21+
when(
22+
mockedClient.request(
23+
objectContaining({
24+
path: "/api/2.1/clusters/get",
25+
method: "GET",
26+
}),
27+
anything()
28+
)
29+
).thenResolve({
1530
...testClusterDetails,
1631
state: "RUNNING",
1732
});

0 commit comments

Comments
 (0)