Skip to content

Commit c836761

Browse files
authored
Merge pull request #33 from eealeivan/cancellation-tokens
Add cancellation tokens to all IMixpanelClient methods.
2 parents bfb7f5c + be4cf7f commit c836761

23 files changed

+921
-370
lines changed

src/Mixpanel/Mixpanel.Tests/Mixpanel.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<ItemGroup>
1010
<PackageReference Include="Bogus" Version="34.0.2" />
1111
<PackageReference Include="FluentAssertions" Version="6.7.0" />
12+
<PackageReference Include="Microsoft.TestPlatform.TestHost" Version="17.2.0" />
1213
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
1314
<PackageReference Include="NUnit" Version="3.13.3" />
1415
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />

src/Mixpanel/Mixpanel.Tests/MixpanelClient/HttpMockMixpanelConfig.cs

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,38 +8,57 @@
88

99
namespace Mixpanel.Tests.MixpanelClient
1010
{
11-
public class HttpMockMixpanelConfig
11+
public class HttpMockMixpanelConfig<TMessage> where TMessage : class
1212
{
1313
public MixpanelConfig Instance { get; }
14-
public List<(string Endpoint, JObject Message)> Messages { get; }
14+
public List<(string Endpoint, TMessage Message)> Messages { get; }
15+
public bool RequestCancelled { get; private set; }
1516

16-
public HttpMockMixpanelConfig(MixpanelConfig config)
17+
public HttpMockMixpanelConfig(MixpanelConfig config = null)
1718
{
1819
Instance = config ?? new MixpanelConfig();
19-
Messages = new List<(string Endpoint, JObject Message)>();
20+
Messages = new List<(string Endpoint, TMessage Message)>();
2021

2122
if (Instance.AsyncHttpPostFn != null)
2223
{
2324
throw new Exception("AsyncHttpPostFn is expected to be null.");
2425
}
2526

26-
Instance.AsyncHttpPostFn = (endpoint, data) =>
27+
Instance.AsyncHttpPostFn = async (endpoint, data, cancellationToken) =>
2728
{
29+
if (cancellationToken.CanBeCanceled)
30+
{
31+
cancellationToken.WaitHandle.WaitOne(TimeSpan.FromSeconds(1));
32+
}
33+
34+
RequestCancelled = cancellationToken.IsCancellationRequested;
35+
cancellationToken.ThrowIfCancellationRequested();
36+
2837
Messages.Add((endpoint, ParseMessageData(data)));
29-
return Task.FromResult(true);
38+
return await Task.FromResult(true);
3039
};
3140
}
3241

33-
private JObject ParseMessageData(string data)
42+
private TMessage ParseMessageData(string data)
3443
{
3544
// Can't use JObject.Parse because it's not possible to disable DateTime parsing
3645
using (var stringReader = new StringReader(GetJsonFromData(data)))
3746
{
3847
using (JsonReader jsonReader = new JsonTextReader(stringReader))
3948
{
4049
jsonReader.DateParseHandling = DateParseHandling.None;
41-
JObject msg = JObject.Load(jsonReader);
42-
return msg;
50+
51+
if (typeof(TMessage) == typeof(JObject))
52+
{
53+
return JObject.Load(jsonReader) as TMessage;
54+
}
55+
56+
if (typeof(TMessage) == typeof(JArray))
57+
{
58+
return JArray.Load(jsonReader) as TMessage;
59+
}
60+
61+
throw new NotSupportedException($"{typeof(TMessage)} is not supported.");
4362
}
4463
}
4564
}

src/Mixpanel/Mixpanel.Tests/MixpanelClient/MixpanelClientHttpTests.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,13 @@ public void SetUp()
3737
() => client.PeopleUnsetAsync(DistinctId, StringPropertyArray),
3838
() => client.PeopleDeleteAsync(DistinctId),
3939
() => client.PeopleTrackChargeAsync(DistinctId, DecimalPropertyValue),
40-
() => client.SendAsync(new MixpanelMessage
40+
() => client.SendAsync(new[]
4141
{
42-
Kind = MessageKind.PeopleSet,
43-
Data = DictionaryWithStringProperty
42+
new MixpanelMessage
43+
{
44+
Kind = MessageKind.PeopleSet,
45+
Data = DictionaryWithStringProperty
46+
}
4447
})
4548
};
4649
}
@@ -49,7 +52,7 @@ private MixpanelConfig GetConfig()
4952
{
5053
return new MixpanelConfig
5154
{
52-
AsyncHttpPostFn = (endpoint, data) =>
55+
AsyncHttpPostFn = (endpoint, data, cancellationToken) =>
5356
{
5457
urls.Add(endpoint);
5558
return Task.FromResult(true);
Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,69 @@
11
using System.Linq;
2+
using System.Threading;
23
using System.Threading.Tasks;
4+
using Bogus;
5+
using FluentAssertions;
36
using Newtonsoft.Json;
47
using Newtonsoft.Json.Linq;
58
using NUnit.Framework;
69

710
namespace Mixpanel.Tests.MixpanelClient
811
{
912
[TestFixture]
10-
public class MixpanelClientSendJsonTests : MixpanelClientTestsBase
13+
public class MixpanelClientSendJsonTests
1114
{
1215
[Test]
13-
public async Task When_SendAsync_Then_CorrectDataSent()
16+
public async Task SendAsync_TrackMessage_CorrectDataSent()
1417
{
15-
bool result = await Client.SendJsonAsync(MixpanelMessageEndpoint.Track, CreateJsonMessage());
18+
// Arrange
19+
var httpMockMixpanelConfig = new HttpMockMixpanelConfig<JObject>();
20+
var client = new Mixpanel.MixpanelClient(httpMockMixpanelConfig.Instance);
21+
var message = CreateJsonMessage();
1622

17-
Assert.That(result, Is.True);
18-
Assert.That(HttpPostEntries.Single().Endpoint, Is.EqualTo(TrackUrl));
19-
CheckSendJsonMessage();
23+
// Act
24+
var result = await client.SendJsonAsync(MixpanelMessageEndpoint.Track, message);
25+
26+
// Assert
27+
result.Should().BeTrue();
28+
var (endpoint, sentMessage) = httpMockMixpanelConfig.Messages.Single();
29+
endpoint.Should().Be("https://api.mixpanel.com/track");
30+
sentMessage.ToString(Formatting.None).Should().Be(message);
31+
}
32+
33+
[Test]
34+
public void SendAsync_CancellationRequested_RequestCancelled()
35+
{
36+
// Arrange
37+
var httpMockMixpanelConfig = new HttpMockMixpanelConfig<JObject>();
38+
var cancellationTokenSource = new CancellationTokenSource();
39+
var client = new Mixpanel.MixpanelClient(httpMockMixpanelConfig.Instance);
40+
var jsonMessage = CreateJsonMessage();
41+
42+
// Act
43+
var task = Task.Factory.StartNew(
44+
async () => await client.SendJsonAsync(
45+
MixpanelMessageEndpoint.Track, jsonMessage, cancellationTokenSource.Token));
46+
cancellationTokenSource.Cancel();
47+
task.Wait();
48+
49+
// Assert
50+
httpMockMixpanelConfig.RequestCancelled.Should().BeTrue();
2051
}
2152

2253
private string CreateJsonMessage()
2354
{
55+
var randomizer = new Randomizer();
2456
var message = new
2557
{
26-
@event = Event,
58+
@event = randomizer.Words(),
2759
properties = new
2860
{
29-
token = Token,
30-
distinct_id = DistinctId,
31-
StringProperty = StringPropertyValue
61+
token = randomizer.AlphaNumeric(30),
62+
distinct_id = randomizer.AlphaNumeric(10)
3263
}
3364
};
34-
string messageJson = JsonConvert.SerializeObject(message);
35-
return messageJson;
36-
}
3765

38-
private void CheckSendJsonMessage()
39-
{
40-
var msg = ParseMessageData(HttpPostEntries.Single().Data);
41-
Assert.That(msg.Count, Is.EqualTo(2));
42-
Assert.That(msg["event"].Value<string>(), Is.EqualTo(Event));
43-
var props = (JObject)msg["properties"];
44-
Assert.That(props.Count, Is.EqualTo(3));
45-
Assert.That(props["token"].Value<string>(), Is.EqualTo(Token));
46-
Assert.That(props["distinct_id"].Value<string>(), Is.EqualTo(DistinctId));
47-
Assert.That(props[StringPropertyName].Value<string>(), Is.EqualTo(StringPropertyValue));
66+
return JsonConvert.SerializeObject(message);
4867
}
4968
}
5069
}

0 commit comments

Comments
 (0)