diff --git a/NucuCar.UnitTests/NucuCar.Common.Tests/MockHttpClient.cs b/NucuCar.UnitTests/NucuCar.Common.Tests/MockHttpClient.cs new file mode 100644 index 0000000..b738c8b --- /dev/null +++ b/NucuCar.UnitTests/NucuCar.Common.Tests/MockHttpClient.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using System.Net.Http; +using System.Threading.Tasks; +using HttpClient = NucuCar.Common.HttpClient; + +namespace NucuCar.UnitTests.NucuCar.Common.Tests +{ + public class MockHttpClient : HttpClient + { + public List SendAsyncArgCalls; + public List SendAsyncResponses; + + private int _sendAsyncCallCounter; + + public MockHttpClient(string baseAddress) : base(baseAddress) + { + _sendAsyncCallCounter = 0; + SendAsyncArgCalls = new List(); + SendAsyncResponses = new List(); + } + + public override Task SendAsync(HttpRequestMessage requestMessage) + { + SendAsyncArgCalls.Add(requestMessage); + var response = SendAsyncResponses[_sendAsyncCallCounter]; + _sendAsyncCallCounter += 1; + return Task.FromResult(response); + } + } +} \ No newline at end of file diff --git a/NucuCar.UnitTests/NucuCar.Telemetry.Tests/TelemetryPublisherFirestoreTest.cs b/NucuCar.UnitTests/NucuCar.Telemetry.Tests/TelemetryPublisherFirestoreTest.cs index 3f28767..7e82f7d 100644 --- a/NucuCar.UnitTests/NucuCar.Telemetry.Tests/TelemetryPublisherFirestoreTest.cs +++ b/NucuCar.UnitTests/NucuCar.Telemetry.Tests/TelemetryPublisherFirestoreTest.cs @@ -2,11 +2,12 @@ using System; using System.Collections.Generic; using System.Net; using System.Net.Http; +using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; -using Moq; using NucuCar.Domain.Telemetry; using NucuCar.Telemetry; +using NucuCar.UnitTests.NucuCar.Common.Tests; using Xunit; using HttpClient = NucuCar.Common.HttpClient; @@ -77,31 +78,20 @@ namespace NucuCar.UnitTests.NucuCar.Telemetry.Tests ConnectionString = "ProjectId=test;CollectionName=test" }; var publisher = new MockTelemetryPublisherFirestore(opts); - var mockHttpClient = new Mock("http://testing.com"); - mockHttpClient.Setup(c => c.SendAsync(It.IsAny())) - .Returns(Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK))); - - publisher.SetHttpClient(mockHttpClient.Object); + var mockHttpClient = new MockHttpClient("http://testing.com"); + mockHttpClient.SendAsyncResponses.Add(new HttpResponseMessage(HttpStatusCode.OK)); + publisher.SetHttpClient(mockHttpClient); publisher.SetMockData(new Dictionary {["testData"] = 1}); // Run await publisher.PublishAsync(CancellationToken.None); // Assert - var expectedContent = "{\"fields\":{\"testData\":{\"integerValue\":1}}}"; - mockHttpClient.Verify( - m => m.SendAsync( - It.Is( - request => request.Method.Equals(HttpMethod.Post)))); - mockHttpClient.Verify( - m => m.SendAsync( - It.Is( - request => request.RequestUri.Equals(new Uri("http://testing.com"))))); - mockHttpClient.Verify( - m => m.SendAsync( - It.Is( - request => request.Content.ReadAsStringAsync().GetAwaiter().GetResult() - .Equals(expectedContent)))); + var request = mockHttpClient.SendAsyncArgCalls[0]; + Assert.Equal(HttpMethod.Post, request.Method); + Assert.Equal(new Uri("http://testing.com"), request.RequestUri); + Assert.Equal("{\"fields\":{\"testData\":{\"integerValue\":1}}}", + request.Content.ReadAsStringAsync().GetAwaiter().GetResult()); } [Fact] @@ -113,11 +103,10 @@ namespace NucuCar.UnitTests.NucuCar.Telemetry.Tests ConnectionString = "ProjectId=test;CollectionName=test" }; var publisher = new MockTelemetryPublisherFirestore(opts); - var mockHttpClient = new Mock("http://testing.com"); - mockHttpClient.Setup(c => c.SendAsync(It.IsAny())) - .Returns(Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK))); + var mockHttpClient = new MockHttpClient("http://testing.com"); + mockHttpClient.SendAsyncResponses.Add(new HttpResponseMessage(HttpStatusCode.OK)); - publisher.SetHttpClient(mockHttpClient.Object); + publisher.SetHttpClient(mockHttpClient); publisher.SetMockData(new Dictionary {["testData"] = 1}); var cts = new CancellationTokenSource(); cts.Cancel(); @@ -126,7 +115,7 @@ namespace NucuCar.UnitTests.NucuCar.Telemetry.Tests await publisher.PublishAsync(cts.Token); // Assert - mockHttpClient.Verify(m => m.SendAsync(It.IsAny()), Times.Never()); + Assert.Equal(mockHttpClient.SendAsyncArgCalls.Count, 0); } [Fact] @@ -135,27 +124,49 @@ namespace NucuCar.UnitTests.NucuCar.Telemetry.Tests // Setup var opts = new TelemetryPublisherBuilderOptions() { - ConnectionString = "ProjectId=test;CollectionName=test" + ConnectionString = + "ProjectId=test;CollectionName=test;WebApiKey=TAPIKEY;WebApiEmail=t@emai.com;WebApiPassword=tpass" }; var publisher = new MockTelemetryPublisherFirestore(opts); - var mockHttpClient = new Mock("http://testing.com"); - mockHttpClient.SetupSequence(c => c.SendAsync(It.IsAny())) - .Returns(Task.FromResult(new HttpResponseMessage(HttpStatusCode.Forbidden))) - .Returns(Task.FromResult( - new HttpResponseMessage(HttpStatusCode.OK) - {Content = new StringContent("{\"idToken\":\"testauthtoken\"}")} - )) - .Returns(Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK))); + var mockHttpClient = new MockHttpClient("http://testing.com"); + mockHttpClient.SendAsyncResponses.Add(new HttpResponseMessage(HttpStatusCode.Forbidden)); + mockHttpClient.SendAsyncResponses.Add(new HttpResponseMessage(HttpStatusCode.OK) + { + Content = new StringContent("{\"idToken\":\"testauthtoken\"}") + }); + mockHttpClient.SendAsyncResponses.Add(new HttpResponseMessage(HttpStatusCode.OK)); - publisher.SetHttpClient(mockHttpClient.Object); + publisher.SetHttpClient(mockHttpClient); publisher.SetMockData(new Dictionary {["testData"] = 1}); // Run await publisher.PublishAsync(CancellationToken.None); // Assert - // Can't verify because moq doesn't support that, damn C#. + Assert.Equal(3, mockHttpClient.SendAsyncArgCalls.Count); + + // 1st request - auth denied + Assert.Equal(HttpMethod.Post, mockHttpClient.SendAsyncArgCalls[0].Method); + Assert.Equal(new Uri("http://testing.com"), mockHttpClient.SendAsyncArgCalls[0].RequestUri); + Assert.Equal("{\"fields\":{\"testData\":{\"integerValue\":1}}}", + mockHttpClient.SendAsyncArgCalls[0].Content.ReadAsStringAsync().GetAwaiter().GetResult()); + + // 2st request - authorizing + Assert.Equal(HttpMethod.Post, mockHttpClient.SendAsyncArgCalls[1].Method); + Assert.Equal(new Uri("https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=TAPIKEY"), + mockHttpClient.SendAsyncArgCalls[1].RequestUri); + Assert.Equal("{\"email\":\"t@emai.com\",\"password\":\"tpass\",\"returnSecureToken\":true}", + mockHttpClient.SendAsyncArgCalls[1].Content.ReadAsStringAsync().GetAwaiter().GetResult()); + + + // 3st request with authorization + Assert.Equal(HttpMethod.Post, mockHttpClient.SendAsyncArgCalls[2].Method); + Assert.Equal(new Uri("http://testing.com"), mockHttpClient.SendAsyncArgCalls[2].RequestUri); + Assert.Equal("{\"fields\":{\"testData\":{\"integerValue\":1}}}", + mockHttpClient.SendAsyncArgCalls[2].Content.ReadAsStringAsync().GetAwaiter().GetResult()); + Assert.Equal(new AuthenticationHeaderValue("Bearer", "testauthtoken"), + mockHttpClient.SendAsyncArgCalls[2].Headers.Authorization); } } } \ No newline at end of file diff --git a/NucuCar.sln.DotSettings.user b/NucuCar.sln.DotSettings.user index f13c6ee..b33993d 100644 --- a/NucuCar.sln.DotSettings.user +++ b/NucuCar.sln.DotSettings.user @@ -3,43 +3,29 @@ <Assembly Path="/home/denis/.nuget/packages/iot.device.bindings/1.0.0/lib/netcoreapp2.1/Iot.Device.Bindings.dll" /> <Assembly Path="/home/denis/.nuget/packages/firebaseresttranslator/0.1.1/lib/netcoreapp3.0/FirebaseRestTranslator.dll" /> </AssemblyExplorer> - <SessionState ContinuousTestingIsOn="False" ContinuousTestingMode="0" FrameworkVersion="{x:Null}" IsLocked="False" Name="Test_PublishAsync_Authorization_OK" PlatformMonoPreference="{x:Null}" PlatformType="{x:Null}" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> + <SessionState ContinuousTestingIsOn="False" ContinuousTestingMode="0" FrameworkVersion="{x:Null}" IsLocked="False" Name="Test_PublishAsync_Authorization_OK" PlatformMonoPreference="{x:Null}" PlatformType="{x:Null}" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <TestAncestor> - <TestId>xUnit::C6F07921-1052-4945-911E-F328A622F229::.NETCoreApp,Version=v3.0::NucuCar.UnitTests.NucuCar.Telemetry.Tests.TelemetryPublisherFirestoreTest.Test_PublishAsync_Authorization_OK</TestId> + <TestId>xUnit::C6F07921-1052-4945-911E-F328A622F229::.NETCoreApp,Version=v3.1::NucuCar.UnitTests.NucuCar.Telemetry.Tests.TelemetryPublisherFirestoreTest.Test_PublishAsync_Authorization_OK</TestId> </TestAncestor> </SessionState> + <SessionState ContinuousTestingIsOn="False" ContinuousTestingMode="0" FrameworkVersion="{x:Null}" IsLocked="False" Name="Session" PlatformMonoPreference="{x:Null}" PlatformType="{x:Null}" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Or> <Or> - <Or> - <Or> - <Or> - <Or> - <TestAncestor> - <TestId>xUnit::C6F07921-1052-4945-911E-F328A622F229::.NETCoreApp,Version=v3.0::NucuCar.UnitTests.NucuCar.Telemetry.Tests.TelemetryPublisherFirestoreTest.Test_PublishAsync_OK</TestId> - </TestAncestor> - <TestAncestor> - <TestId>xUnit::C6F07921-1052-4945-911E-F328A622F229::.NETCoreApp,Version=v3.0::NucuCar.UnitTests.NucuCar.Telemetry.Tests.TelemetryPublisherFirestoreTest.Test_PublishAsync_BadProjectId</TestId> - </TestAncestor> - </Or> - <TestAncestor> - <TestId>xUnit::C6F07921-1052-4945-911E-F328A622F229::.NETCoreApp,Version=v3.0::NucuCar.UnitTests.NucuCar.Telemetry.Tests.TelemetryPublisherFirestoreTest.Test_PublishAsync_CollectiontName</TestId> - </TestAncestor> - </Or> - <TestAncestor> - <TestId>xUnit::C6F07921-1052-4945-911E-F328A622F229::.NETCoreApp,Version=v3.0::NucuCar.UnitTests.NucuCar.Telemetry.Tests.TelemetryPublisherFirestoreTest.Test_PublishAsync_Error_Timeout</TestId> - </TestAncestor> - </Or> - <TestAncestor> - <TestId>xUnit::C6F07921-1052-4945-911E-F328A622F229::.NETCoreApp,Version=v3.0::NucuCar.UnitTests.NucuCar.Telemetry.Tests.TelemetryPublisherFirestoreTest.Test_PublishAsync_Cancel</TestId> - </TestAncestor> - </Or> <TestAncestor> - <TestId>xUnit::C6F07921-1052-4945-911E-F328A622F229::.NETCoreApp,Version=v3.0::NucuCar.UnitTests.NucuCar.Telemetry.Tests.TelemetryPublisherFirestoreTest.Test_PublishAsync_UnknownError</TestId> + <TestId>xUnit::C6F07921-1052-4945-911E-F328A622F229::.NETCoreApp,Version=v3.1::NucuCar.UnitTests.NucuCar.Telemetry.Tests.TelemetryPublisherFirestoreTest.Test_PublishAsync_OK</TestId> + </TestAncestor> + <TestAncestor> + <TestId>xUnit::C6F07921-1052-4945-911E-F328A622F229::.NETCoreApp,Version=v3.1::NucuCar.UnitTests.NucuCar.Telemetry.Tests.TelemetryPublisherFirestoreTest.Test_PublishAsync_Cancel</TestId> </TestAncestor> </Or> <TestAncestor> - <TestId>xUnit::C6F07921-1052-4945-911E-F328A622F229::.NETCoreApp,Version=v3.0::NucuCar.UnitTests.NucuCar.Telemetry.Tests.TelemetryPublisherFirestoreTest.Test_PublishAsync_AuthorizationFail</TestId> + <TestId>xUnit::C6F07921-1052-4945-911E-F328A622F229::.NETCoreApp,Version=v3.1::NucuCar.UnitTests.NucuCar.Telemetry.Tests.TelemetryPublisherFirestoreTest.Test_PublishAsync_Authorization_OK</TestId> </TestAncestor> </Or> +</SessionState> + <SessionState ContinuousTestingIsOn="False" ContinuousTestingMode="0" FrameworkVersion="{x:Null}" IsLocked="False" Name="Test_PublishAsync_OK" PlatformMonoPreference="{x:Null}" PlatformType="{x:Null}" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> + <TestAncestor> + <TestId>xUnit::C6F07921-1052-4945-911E-F328A622F229::.NETCoreApp,Version=v3.1::NucuCar.UnitTests.NucuCar.Telemetry.Tests.TelemetryPublisherFirestoreTest.Test_PublishAsync_OK</TestId> + </TestAncestor> </SessionState> \ No newline at end of file