Skip to content

Commit e5175fd

Browse files
committed
Refactor test infrastructure
1 parent 817f009 commit e5175fd

File tree

137 files changed

+837
-319
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

137 files changed

+837
-319
lines changed

appveyor.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ image: Visual Studio 2017
44
environment:
55
COVERALLS_REPO_TOKEN:
66
secure: T0PmP8uyzCseacBCDRBlti2y9Tz5DL6fknea0MKWvbPYrzADmLY2/5kOTfYIsPUk
7-
# If you bump this, don't forget to bump `MinimumMockVersion` in `BaseStripeTest.cs` as well.
7+
# If you bump this, don't forget to bump `MinimumMockVersion` in `StripeMockFixture.cs` as well.
88
STRIPE_MOCK_VERSION: 0.39.0
99

1010
deploy:

src/StripeTests/BaseStripeTest.cs

+47-141
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,44 @@
11
namespace StripeTests
22
{
3-
using System;
43
using System.IO;
5-
using System.Linq;
6-
using System.Net;
74
using System.Net.Http;
85
using System.Reflection;
96
using System.Text;
10-
using System.Threading;
11-
12-
using Moq;
13-
using Moq.Protected;
14-
using Stripe;
7+
using Xunit;
158

9+
[Collection("stripe-mock tests")]
1610
public class BaseStripeTest
1711
{
18-
/// <value>Minimum required version of stripe-mock</value>
19-
/// <remarks>
20-
/// If you bump this, don't forget to bump `STRIPE_MOCK_VERSION` in appveyor.yml as well.
21-
/// </remarks>
22-
private const string MockMinimumVersion = "0.39.0";
23-
24-
private static Mock<HttpClientHandler> mockHandler;
25-
26-
private static string port;
27-
28-
// Lazy initializer to ensure that initialization is run only once even when running tests
29-
// in parallel.
30-
private static Lazy<object> initializer = new Lazy<object>(InitStripeMock);
31-
3212
public BaseStripeTest()
13+
: this(null, null)
3314
{
34-
// This triggers the lazy initialization. We don't actually care about the value of
35-
// initialized (it will be null anyway), but simply writing `initializer.Value` is not
36-
// a valid statement in C#.
37-
var initialized = initializer.Value;
15+
}
3816

39-
// Reset the mock before each test
40-
mockHandler.Invocations.Clear();
17+
public BaseStripeTest(StripeMockFixture stripeMockFixture)
18+
: this(stripeMockFixture, null)
19+
{
4120
}
4221

43-
/// <summary>
44-
/// Gets fixture data from stripe-mock for a resource expected to be at the given API path.
45-
/// stripe-mock ignores whether IDs are actually valid, so it's only important to make sure
46-
/// that the route exists, rather than the actual resource. It's common to use a symbolic
47-
/// ID stand-in like <code>ch_123</code>
48-
/// </summary>
49-
/// <param name="path">API path to use to get a fixture for stripe-mock</param>
50-
/// <returns>Fixture data encoded as JSON</returns>
51-
protected static string GetFixture(string path)
22+
public BaseStripeTest(MockHttpClientFixture mockHttpClientFixture)
23+
: this(null, mockHttpClientFixture)
5224
{
53-
return GetFixture(path, null);
5425
}
5526

56-
/// <summary>
57-
/// Gets fixture data with expansions specified. Expansions are specified the same way as
58-
/// they are in the normal API like <code>customer</code> or <code>data.customer</code>.
59-
/// Use the special <code>*</code> character to specify that all fields should be
60-
/// expanded.
61-
/// </summary>
62-
/// <param name="path">API path to use to get a fixture for stripe-mock</param>
63-
/// <param name="expansions">Set of expansions that should be applied</param>
64-
/// <returns>Fixture data encoded as JSON</returns>
65-
protected static string GetFixture(string path, string[] expansions)
27+
public BaseStripeTest(StripeMockFixture stripeMockFixture, MockHttpClientFixture mockHttpClientFixture)
6628
{
67-
string url = $"http://localhost:{port}{path}";
29+
this.StripeMockFixture = stripeMockFixture;
30+
this.MockHttpClientFixture = mockHttpClientFixture;
6831

69-
if (expansions != null)
32+
if (this.MockHttpClientFixture != null)
7033
{
71-
string query = string.Join("&", expansions.Select(x => $"expand[]={x}").ToArray());
72-
url += $"?{query}";
34+
// Reset the mock before each test
35+
this.MockHttpClientFixture.Reset();
7336
}
37+
}
7438

75-
using (HttpClient client = new HttpClient())
76-
{
77-
client.DefaultRequestHeaders.Authorization
78-
= new System.Net.Http.Headers.AuthenticationHeaderValue(
79-
"Bearer",
80-
"sk_test_123");
81-
82-
HttpResponseMessage response;
83-
84-
try
85-
{
86-
response = client.GetAsync(url).Result;
87-
}
88-
catch (Exception)
89-
{
90-
throw new Exception(
91-
$"Couldn't reach stripe-mock at `localhost:{port}`. "
92-
+ "Is it running? Please see README for setup instructions.");
93-
}
39+
protected MockHttpClientFixture MockHttpClientFixture { get; }
9440

95-
if (response.StatusCode != HttpStatusCode.OK)
96-
{
97-
throw new Exception(
98-
$"stripe-mock returned status code: {response.StatusCode}.");
99-
}
100-
101-
return response.Content.ReadAsStringAsync().Result;
102-
}
103-
}
41+
protected StripeMockFixture StripeMockFixture { get; }
10442

10543
/// <summary>
10644
/// Gets a resource file and returns its contents in a string.
@@ -110,83 +48,51 @@ protected static string GetFixture(string path, string[] expansions)
11048
protected static string GetResourceAsString(string path)
11149
{
11250
var fullpath = "StripeTests.Resources." + path;
113-
var json = new StreamReader(
51+
var contents = new StreamReader(
11452
typeof(BaseStripeTest).GetTypeInfo().Assembly.GetManifestResourceStream(fullpath),
11553
Encoding.UTF8).ReadToEnd();
11654

117-
return json;
118-
}
119-
120-
protected void AssertRequest(HttpMethod method, string path)
121-
{
122-
mockHandler.Protected().Verify(
123-
"SendAsync",
124-
Times.Once(),
125-
ItExpr.Is<HttpRequestMessage>(m =>
126-
m.Method == method &&
127-
m.RequestUri.AbsolutePath == path),
128-
ItExpr.IsAny<CancellationToken>());
55+
return contents;
12956
}
13057

13158
/// <summary>
132-
/// Checks that stripe-mock is running and that it's a recent enough version.
59+
/// Asserts that a single HTTP request was made with the specified method and path.
13360
/// </summary>
134-
private static object InitStripeMock()
61+
protected void AssertRequest(HttpMethod method, string path)
13562
{
136-
port = Environment.GetEnvironmentVariable("STRIPE_MOCK_PORT") ?? "12111";
137-
string url = $"http://localhost:{port}";
138-
139-
using (HttpClient client = new HttpClient())
63+
if (this.MockHttpClientFixture == null)
14064
{
141-
HttpResponseMessage response;
142-
143-
try
144-
{
145-
response = client.GetAsync(url).Result;
146-
}
147-
catch (Exception)
148-
{
149-
throw new Exception(
150-
$"Couldn't reach stripe-mock at `localhost:{port}`. "
151-
+ "Is it running? Please see README for setup instructions.");
152-
}
153-
154-
string version = response.Headers.GetValues("Stripe-Mock-Version").FirstOrDefault();
155-
156-
if (!version.Equals("master") &&
157-
(CompareVersions(version, MockMinimumVersion) > 0))
158-
{
159-
throw new Exception(
160-
$"Your version of stripe-mock ({version}) is too old. The minimum "
161-
+ $"version to run this test suite is {MockMinimumVersion}. Please see its "
162-
+ "repository for upgrade instructions.");
163-
}
65+
throw new StripeTestException(
66+
"AssertRequest called from a test class that doesn't have access to "
67+
+ "MockHttpClientFixture. Make sure that the constructor for "
68+
+ $"{this.GetType().Name} receives MockHttpClientFixture and calls the "
69+
+ "base constructor.");
16470
}
16571

166-
StripeConfiguration.SetApiBase($"http://localhost:{port}/v1");
167-
StripeConfiguration.SetFilesBase($"http://localhost:{port}/v1");
168-
StripeConfiguration.SetApiKey("sk_test_123");
169-
170-
mockHandler = new Mock<HttpClientHandler>
171-
{
172-
CallBase = true
173-
};
174-
StripeConfiguration.HttpMessageHandler = mockHandler.Object;
175-
176-
return null;
72+
this.MockHttpClientFixture.AssertRequest(method, path);
17773
}
17874

17975
/// <summary>
180-
/// Compares two version strings.
76+
/// Gets fixture data with expansions specified. Expansions are specified the same way as
77+
/// they are in the normal API like <code>customer</code> or <code>data.customer</code>.
78+
/// Use the special <code>*</code> character to specify that all fields should be
79+
/// expanded.
18180
/// </summary>
182-
/// <param name="a">A version string (e.g. "1.2.3").</param>
183-
/// <param name="b">Another version string.</param>
184-
/// <returns>-1 if a > b, 1 if a < b, 0 if a == b</returns>
185-
private static int CompareVersions(string a, string b)
81+
/// <param name="path">API path to use to get a fixture for stripe-mock</param>
82+
/// <param name="expansions">Set of expansions that should be applied</param>
83+
/// <returns>Fixture data encoded as JSON</returns>
84+
protected string GetFixture(string path, string[] expansions = null)
18685
{
187-
var version1 = new Version(a);
188-
var version2 = new Version(b);
189-
return version2.CompareTo(version1);
86+
if (this.StripeMockFixture == null)
87+
{
88+
throw new StripeTestException(
89+
"GetFixture called from a test class that doesn't have access to "
90+
+ "StripeMockFixture. Make sure that the constructor for "
91+
+ $"{this.GetType().Name} receives StripeMockFixture and calls the "
92+
+ "base constructor.");
93+
}
94+
95+
return this.StripeMockFixture.GetFixture(path, expansions);
19096
}
19197
}
19298
}

src/StripeTests/Entities/Accounts/AccountTest.cs

+7-2
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,15 @@ namespace StripeTests
66

77
public class AccountTest : BaseStripeTest
88
{
9+
public AccountTest(StripeMockFixture stripeMockFixture)
10+
: base(stripeMockFixture)
11+
{
12+
}
13+
914
[Fact]
1015
public void Deserialize()
1116
{
12-
string json = GetFixture("/v1/accounts/acct_123");
17+
string json = this.GetFixture("/v1/accounts/acct_123");
1318
var account = JsonConvert.DeserializeObject<Account>(json);
1419
Assert.NotNull(account);
1520
Assert.IsType<Account>(account);
@@ -25,7 +30,7 @@ public void DeserializeWithExpansions()
2530
"business_logo",
2631
};
2732

28-
string json = GetFixture("/v1/accounts/acct_123", expansions);
33+
string json = this.GetFixture("/v1/accounts/acct_123", expansions);
2934
var account = JsonConvert.DeserializeObject<Account>(json);
3035

3136
Assert.NotNull(account);

src/StripeTests/Entities/ApplePayDomains/ApplePayDomainTest.cs

+6-1
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,15 @@ namespace StripeTests
66

77
public class ApplePayDomainTest : BaseStripeTest
88
{
9+
public ApplePayDomainTest(StripeMockFixture stripeMockFixture)
10+
: base(stripeMockFixture)
11+
{
12+
}
13+
914
[Fact]
1015
public void Deserialize()
1116
{
12-
string json = GetFixture("/v1/apple_pay/domains/apwc_123");
17+
string json = this.GetFixture("/v1/apple_pay/domains/apwc_123");
1318
var domain = JsonConvert.DeserializeObject<ApplePayDomain>(json);
1419
Assert.NotNull(domain);
1520
Assert.IsType<ApplePayDomain>(domain);

src/StripeTests/Entities/ApplicationFeeRefunds/ApplicationFeeRefundTest.cs

+6-1
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,15 @@ namespace StripeTests
66

77
public class ApplicationFeeRefundTest : BaseStripeTest
88
{
9+
public ApplicationFeeRefundTest(StripeMockFixture stripeMockFixture)
10+
: base(stripeMockFixture)
11+
{
12+
}
13+
914
[Fact]
1015
public void Deserialize()
1116
{
12-
string json = GetFixture("/v1/application_fees/fee_123/refunds/fr_123");
17+
string json = this.GetFixture("/v1/application_fees/fee_123/refunds/fr_123");
1318
var applicationFeeRefund = JsonConvert.DeserializeObject<ApplicationFeeRefund>(json);
1419
Assert.NotNull(applicationFeeRefund);
1520
Assert.IsType<ApplicationFeeRefund>(applicationFeeRefund);

src/StripeTests/Entities/ApplicationFees/ApplicationFeeTest.cs

+7-2
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,15 @@ namespace StripeTests
66

77
public class ApplicationFeeTest : BaseStripeTest
88
{
9+
public ApplicationFeeTest(StripeMockFixture stripeMockFixture)
10+
: base(stripeMockFixture)
11+
{
12+
}
13+
914
[Fact]
1015
public void Deserialize()
1116
{
12-
string json = GetFixture("/v1/application_fees/fee_123");
17+
string json = this.GetFixture("/v1/application_fees/fee_123");
1318
var applicationFee = JsonConvert.DeserializeObject<ApplicationFee>(json);
1419
Assert.NotNull(applicationFee);
1520
Assert.IsType<ApplicationFee>(applicationFee);
@@ -29,7 +34,7 @@ public void DeserializeWithExpansions()
2934
"originating_transaction",
3035
};
3136

32-
string json = GetFixture("/v1/application_fees/fee_123", expansions);
37+
string json = this.GetFixture("/v1/application_fees/fee_123", expansions);
3338
var applicationFee = JsonConvert.DeserializeObject<ApplicationFee>(json);
3439
Assert.NotNull(applicationFee);
3540
Assert.IsType<ApplicationFee>(applicationFee);

src/StripeTests/Entities/Balance/BalanceTest.cs

+6-1
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,15 @@ namespace StripeTests
66

77
public class BalanceTest : BaseStripeTest
88
{
9+
public BalanceTest(StripeMockFixture stripeMockFixture)
10+
: base(stripeMockFixture)
11+
{
12+
}
13+
914
[Fact]
1015
public void Deserialize()
1116
{
12-
string json = GetFixture("/v1/balance");
17+
string json = this.GetFixture("/v1/balance");
1318
var balance = JsonConvert.DeserializeObject<Balance>(json);
1419
Assert.NotNull(balance);
1520
Assert.IsType<Balance>(balance);

src/StripeTests/Entities/BalanceTransactions/BalanceTransactionTest.cs

+6-1
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,15 @@ namespace StripeTests
77

88
public class BalanceTransactionTest : BaseStripeTest
99
{
10+
public BalanceTransactionTest(StripeMockFixture stripeMockFixture)
11+
: base(stripeMockFixture)
12+
{
13+
}
14+
1015
[Fact]
1116
public void Deserialize()
1217
{
13-
string json = GetFixture("/v1/balance/history/txn_123");
18+
string json = this.GetFixture("/v1/balance/history/txn_123");
1419
var balanceTransaction = JsonConvert.DeserializeObject<BalanceTransaction>(json);
1520
Assert.NotNull(balanceTransaction);
1621
Assert.IsType<BalanceTransaction>(balanceTransaction);

0 commit comments

Comments
 (0)