diff --git a/PactNet.Tests/Core/MockProviderHostConfigTests.cs b/PactNet.Tests/Core/MockProviderHostConfigTests.cs index 629efd15..b6287008 100644 --- a/PactNet.Tests/Core/MockProviderHostConfigTests.cs +++ b/PactNet.Tests/Core/MockProviderHostConfigTests.cs @@ -6,9 +6,9 @@ namespace PactNet.Tests.Core { public class MockProviderHostConfigTests { - private IPactCoreHostConfig GetSubject(int port = 2322, bool enableSsl = false, string consumerName = "My Test Consumer", string providerName = "My Test Provider", PactConfig pactConfig = null) + private IPactCoreHostConfig GetSubject(int port = 2322, bool enableSsl = false, string consumerName = "My Test Consumer", string providerName = "My Test Provider", PactConfig pactConfig = null, string host = "") { - return new MockProviderHostConfig(port, enableSsl, consumerName, providerName, pactConfig ?? new PactConfig()); + return new MockProviderHostConfig(port, enableSsl, consumerName, providerName, pactConfig ?? new PactConfig(), host); } [Fact] @@ -54,6 +54,25 @@ public void Ctor_WhenCalledWithSsl_SetsTheCorrectArgs() Assert.Equal(expectedArguments, config.Arguments); } + [Fact] + public void Ctor_WhenCalledWithHost_SetsTheCorrectArgs() + { + var port = 9332; + var pactConfig = new PactConfig(); + var consumerName = "Cons"; + var providerName = "The best one"; + var enableSsl = true; + var host = "0.0.0.0"; + + var config = GetSubject(port, enableSsl, consumerName, providerName, pactConfig, host); + + var expectedLogFilePath = BuildExpectedLogFilePath(pactConfig.LogDir, providerName); + var expectedPactDir = BuildExpectedPactDir(pactConfig.PactDir); + var expectedArguments = BuildExpectedArguments(port, expectedLogFilePath, expectedPactDir, pactConfig.SpecificationVersion, consumerName, providerName, enableSsl, host); + + Assert.Equal(expectedArguments, config.Arguments); + } + [Fact] public void Ctor_WhenCalledWithNonDefaultLogDirectory_SetsTheCorrectArgs() { @@ -111,17 +130,20 @@ private string BuildExpectedPactDir(string pactDir) } private string BuildExpectedArguments( - int port, - string logFilePath, + int port, + string logFilePath, string pactFileDir, string pactSpecificationVersion, string consumerName, string providerName, - bool enableSsl = false) + bool enableSsl = false, + string host = "") { var sslOption = enableSsl ? " --ssl" : ""; - return $"-p {port} -l \"{logFilePath}\" --pact-dir \"{pactFileDir}\" --pact-specification-version \"{pactSpecificationVersion}\" --consumer \"{consumerName}\" --provider \"{providerName}\"{sslOption}"; + var hostOption = !string.IsNullOrWhiteSpace(host) ? $" --host={host}" : ""; + + return $"-p {port} -l \"{logFilePath}\" --pact-dir \"{pactFileDir}\" --pact-specification-version \"{pactSpecificationVersion}\" --consumer \"{consumerName}\" --provider \"{providerName}\"{sslOption}{hostOption}"; } } } diff --git a/PactNet.Tests/IntegrationTests/FailureIntegrationTestsMyApiPact.cs b/PactNet.Tests/IntegrationTests/FailureIntegrationTestsMyApiPact.cs index f266ffef..2bc5b300 100644 --- a/PactNet.Tests/IntegrationTests/FailureIntegrationTestsMyApiPact.cs +++ b/PactNet.Tests/IntegrationTests/FailureIntegrationTestsMyApiPact.cs @@ -16,10 +16,10 @@ public FailureIntegrationTestsMyApiPact() { var pactConfig = new PactConfig(); - PactBuilder = new PactBuilder((port, enableSsl, consumerName, providerName) => + PactBuilder = new PactBuilder((port, enableSsl, consumerName, providerName, host) => new MockProviderService( - baseUri => new RubyHttpHost(baseUri, "MyConsumer", "MyApi", pactConfig), - port, enableSsl, + baseUri => new RubyHttpHost(baseUri, "MyConsumer", "MyApi", pactConfig), + port, enableSsl, baseUri => new AdminHttpClient(baseUri))) .ServiceConsumer("FailureIntegrationTests") .HasPactWith("MyApi"); diff --git a/PactNet.Tests/IntegrationTests/IntegrationTestsMyApiPact.cs b/PactNet.Tests/IntegrationTests/IntegrationTestsMyApiPact.cs index 3d80ed0a..7371b7d8 100644 --- a/PactNet.Tests/IntegrationTests/IntegrationTestsMyApiPact.cs +++ b/PactNet.Tests/IntegrationTests/IntegrationTestsMyApiPact.cs @@ -16,7 +16,7 @@ public IntegrationTestsMyApiPact() { var pactConfig = new PactConfig(); - PactBuilder = new PactBuilder((port, enableSsl, consumerName, providerName) => + PactBuilder = new PactBuilder((port, enableSsl, consumerName, providerName, host) => new MockProviderService( baseUri => new RubyHttpHost(baseUri, "MyConsumer", "MyApi", pactConfig), port, enableSsl, diff --git a/PactNet.Tests/Mocks/MockHttpService/MockProviderServiceTests.cs b/PactNet.Tests/Mocks/MockHttpService/MockProviderServiceTests.cs index cbbd12e8..116cf680 100644 --- a/PactNet.Tests/Mocks/MockHttpService/MockProviderServiceTests.cs +++ b/PactNet.Tests/Mocks/MockHttpService/MockProviderServiceTests.cs @@ -19,7 +19,7 @@ public class MockProviderServiceTests private FakeHttpMessageHandler _fakeHttpMessageHandler; private int _mockHttpHostFactoryCallCount; - private IMockProviderService GetSubject(int port = 1234, bool enableSsl = false) + private IMockProviderService GetSubject(int port = 1234, bool enableSsl = false, string host = "") { _mockHttpHost = Substitute.For(); _fakeHttpMessageHandler = new FakeHttpMessageHandler(); @@ -33,7 +33,8 @@ private IMockProviderService GetSubject(int port = 1234, bool enableSsl = false) }, port, enableSsl, - baseUri => new AdminHttpClient(baseUri, _fakeHttpMessageHandler)); + baseUri => new AdminHttpClient(baseUri, _fakeHttpMessageHandler), + host); } [Fact] @@ -51,7 +52,7 @@ public void Ctor_WhenCalledWithEnableSslFalse_SetsBaseUriWithHttpScheme() { var mockService = GetSubject(enableSsl: false); - Assert.True(((MockProviderService)mockService).BaseUri.Scheme.ToUpperInvariant().Equals("HTTP"), "BaseUri has a http scheme"); + Assert.True(((MockProviderService)mockService).BaseUri.Scheme.Equals("HTTP", StringComparison.OrdinalIgnoreCase), "BaseUri has a http scheme"); } [Fact] @@ -59,7 +60,15 @@ public void Ctor_WhenCalledWithEnableSslTrue_SetsBaseUriWithHttpsScheme() { var mockService = GetSubject(enableSsl: true); - Assert.True(((MockProviderService)mockService).BaseUri.Scheme.ToUpperInvariant().Equals("HTTPS"), "BaseUri has a https scheme"); + Assert.True(((MockProviderService)mockService).BaseUri.Scheme.Equals("HTTPS", StringComparison.OrdinalIgnoreCase), "BaseUri has a https scheme"); + } + + [Fact] + public void Ctor_WhenCalledWithHost_UsesTheHostInsteadOfLocalhost() + { + var mockService = GetSubject(host: "0.0.0.0"); + + Assert.True(((MockProviderService)mockService).BaseUri.Host.Equals("0.0.0.0"), "BaseUri has a 0.0.0.0 as a host"); } [Fact] diff --git a/PactNet.Tests/PactBuilderTests.cs b/PactNet.Tests/PactBuilderTests.cs index 9d1c776a..60a4bd43 100644 --- a/PactNet.Tests/PactBuilderTests.cs +++ b/PactNet.Tests/PactBuilderTests.cs @@ -75,7 +75,7 @@ public void MockService_WhenCalled_StartIsCalledAndMockProviderServiceIsReturned { var mockMockProviderService = Substitute.For(); - IPactBuilder pactBuilder = new PactBuilder((port, enableSsl, consumerName, providerName) => mockMockProviderService); + IPactBuilder pactBuilder = new PactBuilder((port, enableSsl, consumerName, providerName, host) => mockMockProviderService); pactBuilder .ServiceConsumer("Event Client") @@ -92,7 +92,7 @@ public void MockService_WhenCalledTwice_StopIsCalledTheSecondTime() { var mockMockProviderService = Substitute.For(); - IPactBuilder pactBuilder = new PactBuilder((port, enableSsl, consumerName, providerName) => mockMockProviderService); + IPactBuilder pactBuilder = new PactBuilder((port, enableSsl, consumerName, providerName, host) => mockMockProviderService); pactBuilder .ServiceConsumer("Event Client") @@ -111,7 +111,7 @@ public void MockService_WhenCalled_MockProviderServiceFactoryIsInvokedWithSslNot var calledWithSslEnabled = false; var mockMockProviderService = Substitute.For(); - IPactBuilder pactBuilder = new PactBuilder((port, enableSsl, consumerName, providerName) => + IPactBuilder pactBuilder = new PactBuilder((port, enableSsl, consumerName, providerName, host) => { calledWithSslEnabled = enableSsl; return mockMockProviderService; @@ -132,7 +132,7 @@ public void MockService_WhenCalledWithEnableSslFalse_MockProviderServiceFactoryI var calledWithSslEnabled = false; var mockMockProviderService = Substitute.For(); - IPactBuilder pactBuilder = new PactBuilder((port, enableSsl, consumerName, providerName) => + IPactBuilder pactBuilder = new PactBuilder((port, enableSsl, consumerName, providerName, host) => { calledWithSslEnabled = enableSsl; return mockMockProviderService; @@ -153,7 +153,7 @@ public void MockService_WhenCalledWithEnableSslTrue_MockProviderServiceFactoryIs var calledWithSslEnabled = false; var mockMockProviderService = Substitute.For(); - IPactBuilder pactBuilder = new PactBuilder((port, enableSsl, consumerName, providerName) => + IPactBuilder pactBuilder = new PactBuilder((port, enableSsl, consumerName, providerName, host) => { calledWithSslEnabled = enableSsl; return mockMockProviderService; @@ -174,7 +174,7 @@ public void MockService_WhenCalledWithJsonSerializerSettings_SetsTheGlobalApiSer var serializerSettings = new JsonSerializerSettings(); var mockMockProviderService = Substitute.For(); - IPactBuilder pactBuilder = new PactBuilder((port, enableSsl, consumerName, providerName) => mockMockProviderService); + IPactBuilder pactBuilder = new PactBuilder((port, enableSsl, consumerName, providerName, host) => mockMockProviderService); pactBuilder .ServiceConsumer("Event Client") @@ -197,7 +197,7 @@ public void MockService_WhenCalledWithNoJsonSerializerSettings_DoesNotSetTheGlob { var mockMockProviderService = Substitute.For(); - IPactBuilder pactBuilder = new PactBuilder((port, enableSsl, consumerName, providerName) => mockMockProviderService); + IPactBuilder pactBuilder = new PactBuilder((port, enableSsl, consumerName, providerName, host) => mockMockProviderService); pactBuilder .ServiceConsumer("Event Client") @@ -211,7 +211,7 @@ public void MockService_WhenCalledWithNoJsonSerializerSettings_DoesNotSetTheGlob [Fact] public void MockService_WhenCalledWithoutConsumerNameSet_ThrowsInvalidOperationException() { - IPactBuilder pactBuilder = new PactBuilder((port, ssl, consumerName, providerName) => Substitute.For()); + IPactBuilder pactBuilder = new PactBuilder((port, ssl, consumerName, providerName, host) => Substitute.For()); pactBuilder .HasPactWith("Event API"); @@ -221,7 +221,7 @@ public void MockService_WhenCalledWithoutConsumerNameSet_ThrowsInvalidOperationE [Fact] public void MockService_WhenCalledWithoutProviderNameSet_ThrowsInvalidOperationException() { - IPactBuilder pactBuilder = new PactBuilder((port, ssl, consumerName, providerName) => Substitute.For()); + IPactBuilder pactBuilder = new PactBuilder((port, ssl, consumerName, providerName, hsot) => Substitute.For()); pactBuilder .ServiceConsumer("Event Client"); @@ -243,7 +243,7 @@ public void Build_WhenCalledWithTheMockProviderServiceInitialised_CallsSendAdmin const string testProviderName = "Event API"; var mockProviderService = Substitute.For(); - IPactBuilder pactBuilder = new PactBuilder((port, ssl, consumerName, providerName) => mockProviderService); + IPactBuilder pactBuilder = new PactBuilder((port, ssl, consumerName, providerName, host) => mockProviderService); pactBuilder .ServiceConsumer(testConsumerName) .HasPactWith(testProviderName); @@ -260,7 +260,7 @@ public void Build_WhenCalledWithAnInitialisedMockProviderService_StopIsCalledOnT { var mockMockProviderService = Substitute.For(); - IPactBuilder pactBuilder = new PactBuilder((port, enableSsl, consumerName, providerName) => mockMockProviderService) + IPactBuilder pactBuilder = new PactBuilder((port, enableSsl, consumerName, providerName, host) => mockMockProviderService) .ServiceConsumer("Event Client") .HasPactWith("Event API"); diff --git a/PactNet/Core/MockProviderHostConfig.cs b/PactNet/Core/MockProviderHostConfig.cs index 9fc35cd9..cc6326b5 100644 --- a/PactNet/Core/MockProviderHostConfig.cs +++ b/PactNet/Core/MockProviderHostConfig.cs @@ -11,13 +11,14 @@ internal class MockProviderHostConfig : IPactCoreHostConfig public bool WaitForExit { get; } public IEnumerable Outputters { get; } - public MockProviderHostConfig(int port, bool enableSsl, string consumerName, string providerName, PactConfig config) + public MockProviderHostConfig(int port, bool enableSsl, string consumerName, string providerName, PactConfig config, string host = "") { var logFile = $"{config.LogDir}{providerName.ToLowerSnakeCase()}_mock_service.log"; var sslOption = enableSsl ? " --ssl" : ""; + var hostOption = string.IsNullOrWhiteSpace(host) ? "" : $" --host={host}"; Script = "pact-mock-service"; - Arguments = $"-p {port} -l \"{FixPathForRuby(logFile)}\" --pact-dir \"{FixPathForRuby(config.PactDir)}\" --pact-specification-version \"{config.SpecificationVersion}\" --consumer \"{consumerName}\" --provider \"{providerName}\"{sslOption}"; + Arguments = $"-p {port} -l \"{FixPathForRuby(logFile)}\" --pact-dir \"{FixPathForRuby(config.PactDir)}\" --pact-specification-version \"{config.SpecificationVersion}\" --consumer \"{consumerName}\" --provider \"{providerName}\"{sslOption}{hostOption}"; WaitForExit = false; Outputters = config?.Outputters; } diff --git a/PactNet/IPactBuilder.cs b/PactNet/IPactBuilder.cs index a6fbbc57..c8a6c3c9 100644 --- a/PactNet/IPactBuilder.cs +++ b/PactNet/IPactBuilder.cs @@ -7,8 +7,8 @@ public interface IPactBuilder { IPactBuilder ServiceConsumer(string consumerName); IPactBuilder HasPactWith(string providerName); - IMockProviderService MockService(int port, bool enableSsl = false); - IMockProviderService MockService(int port, JsonSerializerSettings jsonSerializerSettings, bool enableSsl = false); + IMockProviderService MockService(int port, bool enableSsl = false, string host = ""); + IMockProviderService MockService(int port, JsonSerializerSettings jsonSerializerSettings, bool enableSsl = false, string host = ""); void Build(); } } \ No newline at end of file diff --git a/PactNet/Mocks/MockHttpService/Host/RubyHttpHost.cs b/PactNet/Mocks/MockHttpService/Host/RubyHttpHost.cs index ba715f9d..880e5800 100644 --- a/PactNet/Mocks/MockHttpService/Host/RubyHttpHost.cs +++ b/PactNet/Mocks/MockHttpService/Host/RubyHttpHost.cs @@ -11,19 +11,21 @@ internal class RubyHttpHost : IHttpHost private readonly AdminHttpClient _adminHttpClient; internal RubyHttpHost( - IPactCoreHost coreHost, + IPactCoreHost coreHost, AdminHttpClient adminHttpClient) { _coreHost = coreHost; _adminHttpClient = adminHttpClient; } - public RubyHttpHost(Uri baseUri, string consumerName, string providerName, PactConfig config) : + public RubyHttpHost(Uri baseUri, string consumerName, string providerName, PactConfig config) : this(new PactCoreHost( - new MockProviderHostConfig(baseUri.Port, - baseUri.Scheme.ToUpperInvariant().Equals("HTTPS"), + new MockProviderHostConfig(baseUri.Port, + baseUri.Scheme.Equals("HTTPS", StringComparison.OrdinalIgnoreCase), consumerName, - providerName, config)), + providerName, + config, + baseUri.Host)), new AdminHttpClient(baseUri)) { } @@ -35,7 +37,7 @@ private Tuple IsMockProviderServiceRunning() _adminHttpClient.SendAdminHttpRequest(HttpVerb.Get, "/"); return new Tuple(true, null); } - catch(Exception ex) + catch (Exception ex) { return new Tuple(false, ex); } diff --git a/PactNet/Mocks/MockHttpService/MockProviderService.cs b/PactNet/Mocks/MockHttpService/MockProviderService.cs index ba66b682..6a51396d 100644 --- a/PactNet/Mocks/MockHttpService/MockProviderService.cs +++ b/PactNet/Mocks/MockHttpService/MockProviderService.cs @@ -23,19 +23,22 @@ internal MockProviderService( Func hostFactory, int port, bool enableSsl, - Func adminHttpClientFactory) + Func adminHttpClientFactory, + string host = "") { _hostFactory = hostFactory; - BaseUri = new Uri($"{(enableSsl ? "https" : "http")}://localhost:{port}"); + BaseUri = new Uri( + $"{(enableSsl ? "https" : "http")}://{(IsNullOrWhiteSpace(host) ? "localhost" : host)}:{port}"); _adminHttpClient = adminHttpClientFactory(BaseUri); } - public MockProviderService(int port, bool enableSsl, string consumerName, string providerName, PactConfig config) + public MockProviderService(int port, bool enableSsl, string consumerName, string providerName, PactConfig config, string host = "") : this( baseUri => new RubyHttpHost(baseUri, consumerName, providerName, config), port, enableSsl, - baseUri => new AdminHttpClient(baseUri)) + baseUri => new AdminHttpClient(baseUri), + host) { } @@ -81,7 +84,7 @@ public IMockProviderService With(ProviderServiceRequest request) } _request = request; - + return this; } diff --git a/PactNet/PactBuilder.cs b/PactNet/PactBuilder.cs index 2a12c9b4..d2bc967d 100644 --- a/PactNet/PactBuilder.cs +++ b/PactNet/PactBuilder.cs @@ -11,10 +11,11 @@ public class PactBuilder : IPactBuilder { public string ConsumerName { get; private set; } public string ProviderName { get; private set; } - private readonly Func _mockProviderServiceFactory; + private readonly Func _mockProviderServiceFactory; + private IMockProviderService _mockProviderService; - internal PactBuilder(Func mockProviderServiceFactory) + internal PactBuilder(Func mockProviderServiceFactory) { _mockProviderServiceFactory = mockProviderServiceFactory; } @@ -25,7 +26,7 @@ public PactBuilder() } public PactBuilder(PactConfig config) - : this((port, enableSsl, consumerName, providerName) => new MockProviderService(port, enableSsl, consumerName, providerName, config)) + : this((port, enableSsl, consumerName, providerName, host) => new MockProviderService(port, enableSsl, consumerName, providerName, config, host)) { } @@ -53,12 +54,12 @@ public IPactBuilder HasPactWith(string providerName) return this; } - public IMockProviderService MockService(int port, bool enableSsl = false) + public IMockProviderService MockService(int port, bool enableSsl = false, string host = "") { - return MockService(port, jsonSerializerSettings: null, enableSsl: enableSsl); + return MockService(port, jsonSerializerSettings: null, enableSsl: enableSsl, host: host); } - - public IMockProviderService MockService(int port, JsonSerializerSettings jsonSerializerSettings, bool enableSsl = false) + + public IMockProviderService MockService(int port, JsonSerializerSettings jsonSerializerSettings, bool enableSsl = false, string host = "") { if (String.IsNullOrEmpty(ConsumerName)) { @@ -80,7 +81,7 @@ public IMockProviderService MockService(int port, JsonSerializerSettings jsonSer JsonConfig.ApiSerializerSettings = jsonSerializerSettings; } - _mockProviderService = _mockProviderServiceFactory(port, enableSsl, ConsumerName, ProviderName); + _mockProviderService = _mockProviderServiceFactory(port, enableSsl, ConsumerName, ProviderName, host); _mockProviderService.Start();