Skip to content

Commit 5055a00

Browse files
feat: deserialize info, models and servers for datacontract-specification (#214)
* feat: deserialize info, models and servers for datacontract-specification * [CodeFactor] Apply fixes --------- Co-authored-by: codefactor-io <support@codefactor.io>
1 parent c25a330 commit 5055a00

33 files changed

+1586
-0
lines changed

Packata.sln

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Packata.OpenDataContract",
5959
EndProject
6060
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Packata.OpenDataContract.Testing", "src\Packata.OpenDataContract.Testing\Packata.OpenDataContract.Testing.csproj", "{368904A6-1BC4-1886-185A-74268613406A}"
6161
EndProject
62+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Specs", "Specs", "{A527EAAB-BE17-450B-BF1B-9750149F7F71}"
63+
EndProject
64+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Packata.DataContractSpecification", "src\Packata.DataContractSpecification\Packata.DataContractSpecification.csproj", "{C2323DD6-CAAA-601E-C75D-6B6F9F212714}"
65+
EndProject
66+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Packata.DataContractSpecification.Testing", "src\Packata.DataContractSpecification.Testing\Packata.DataContractSpecification.Testing.csproj", "{CF6B0DB4-15DC-8857-D06E-852D74C83C3A}"
67+
EndProject
6268
Global
6369
GlobalSection(SolutionConfigurationPlatforms) = preSolution
6470
Debug|Any CPU = Debug|Any CPU
@@ -105,6 +111,14 @@ Global
105111
{368904A6-1BC4-1886-185A-74268613406A}.Debug|Any CPU.Build.0 = Debug|Any CPU
106112
{368904A6-1BC4-1886-185A-74268613406A}.Release|Any CPU.ActiveCfg = Release|Any CPU
107113
{368904A6-1BC4-1886-185A-74268613406A}.Release|Any CPU.Build.0 = Release|Any CPU
114+
{C2323DD6-CAAA-601E-C75D-6B6F9F212714}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
115+
{C2323DD6-CAAA-601E-C75D-6B6F9F212714}.Debug|Any CPU.Build.0 = Debug|Any CPU
116+
{C2323DD6-CAAA-601E-C75D-6B6F9F212714}.Release|Any CPU.ActiveCfg = Release|Any CPU
117+
{C2323DD6-CAAA-601E-C75D-6B6F9F212714}.Release|Any CPU.Build.0 = Release|Any CPU
118+
{CF6B0DB4-15DC-8857-D06E-852D74C83C3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
119+
{CF6B0DB4-15DC-8857-D06E-852D74C83C3A}.Debug|Any CPU.Build.0 = Debug|Any CPU
120+
{CF6B0DB4-15DC-8857-D06E-852D74C83C3A}.Release|Any CPU.ActiveCfg = Release|Any CPU
121+
{CF6B0DB4-15DC-8857-D06E-852D74C83C3A}.Release|Any CPU.Build.0 = Release|Any CPU
108122
EndGlobalSection
109123
GlobalSection(SolutionProperties) = preSolution
110124
HideSolutionNode = FALSE
@@ -116,6 +130,8 @@ Global
116130
{8BAE720D-3F03-4D53-A5B4-CDA95DA97697} = {3EC93812-5079-426E-89E5-7785B87B7D55}
117131
{357BFF0A-876E-BDD1-52C3-F4F9BDD35AF8} = {93ECC912-96B7-463A-BAA4-9A2274C97329}
118132
{CB16B305-A39F-23A9-FDCB-7996C42F2EC5} = {93ECC912-96B7-463A-BAA4-9A2274C97329}
133+
{39148ED5-15AF-D57C-21AB-5F9E32745C7B} = {A527EAAB-BE17-450B-BF1B-9750149F7F71}
134+
{368904A6-1BC4-1886-185A-74268613406A} = {A527EAAB-BE17-450B-BF1B-9750149F7F71}
119135
EndGlobalSection
120136
GlobalSection(ExtensibilityGlobals) = postSolution
121137
SolutionGuid = {4AF64100-8E3B-4ACF-8266-89231A365F92}

appveyor.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ test_script:
6262
$globalTestResult += $LastExitCode
6363
dotnet test src/Packata.OpenDataContract.Testing -c Release /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:Exclude="[Packata.*.Testing]*" /p:CoverletOutput=../../.coverage/coverage.Packata.OpenDataContract.xml --test-adapter-path:. --logger:Appveyor --no-build --nologo
6464
$globalTestResult += $LastExitCode
65+
dotnet test src/Packata.DataContractSpecification.Testing -c Release /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:Exclude="[Packata.*.Testing]*" /p:CoverletOutput=../../.coverage/coverage.Packata.DataContractSpecification.xml --test-adapter-path:. --logger:Appveyor --no-build --nologo
66+
$globalTestResult += $LastExitCode
6567
if($globalTestResult -ne 0) { $host.SetShouldExit($globalTestResult) }
6668
6769
- pwsh: |
@@ -77,6 +79,7 @@ after_test:
7779
- dotnet pack src/Packata.Provisioners -p:version="%GitVersion_SemVer%" -c Release --include-symbols --no-build --nologo
7880
- dotnet pack src/Packata.Storages -p:version="%GitVersion_SemVer%" -c Release --include-symbols --no-build --nologo
7981
- dotnet pack src/Packata.OpenDataContract -p:version="%GitVersion_SemVer%" -c Release --include-symbols --no-build --nologo
82+
- dotnet pack src/Packata.DataContractSpecification -p:version="%GitVersion_SemVer%" -c Release --include-symbols --no-build --nologo
8083

8184
artifacts:
8285
- path: '**\*.nupkg'
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<ItemGroup>
3+
<None Remove="Serialization\Yaml\Resources\covid-cases.yaml" />
4+
</ItemGroup>
5+
<ItemGroup>
6+
<EmbeddedResource Include="Serialization\Yaml\Resources\servers.yaml" />
7+
<EmbeddedResource Include="Serialization\Yaml\Resources\orders-latest.yaml" />
8+
<EmbeddedResource Include="Serialization\Yaml\Resources\orders-latest-nested.yaml" />
9+
<EmbeddedResource Include="Serialization\Yaml\Resources\covid-cases.yaml" />
10+
</ItemGroup>
11+
<ItemGroup>
12+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
13+
<PackageReference Include="Moq" Version="4.20.72" />
14+
<PackageReference Include="NUnit" Version="4.3.2" />
15+
<PackageReference Include="NUnit.Analyzers" Version="4.8.1">
16+
<PrivateAssets>all</PrivateAssets>
17+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
18+
</PackageReference>
19+
<PackageReference Include="NUnit3TestAdapter" Version="5.0.0" />
20+
<PackageReference Include="Appveyor.TestLogger" Version="2.0.0" />
21+
</ItemGroup>
22+
<ItemGroup>
23+
<PackageReference Include="coverlet.msbuild" Version="6.0.4">
24+
<PrivateAssets>all</PrivateAssets>
25+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
26+
</PackageReference>
27+
<PackageReference Include="coverlet.collector" Version="6.0.4">
28+
<PrivateAssets>all</PrivateAssets>
29+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
30+
</PackageReference>
31+
</ItemGroup>
32+
<ItemGroup>
33+
<PackageReference Update="DotNet.ReproducibleBuilds" Version="1.2.25">
34+
<PrivateAssets>all</PrivateAssets>
35+
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
36+
</PackageReference>
37+
</ItemGroup>
38+
<ItemGroup>
39+
<ProjectReference Include="..\Packata.Core\Packata.Core.csproj" />
40+
<ProjectReference Include="..\Packata.DataContractSpecification\Packata.DataContractSpecification.csproj" />
41+
</ItemGroup></Project>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
using NUnit.Framework;
8+
using Packata.DataContractSpecification.Serialization;
9+
10+
namespace Packata.DataContractSpecification.Testing.Serialization;
11+
12+
public abstract class BaseDataContractSerializerTests
13+
{
14+
protected abstract IDataContractSerializer GetSerializer();
15+
16+
protected abstract string GetFormat();
17+
}
Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Reflection;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
using Castle.Core.Resource;
8+
using Moq;
9+
using Newtonsoft.Json;
10+
using NUnit.Framework;
11+
using Packata.Core.Storage;
12+
using Packata.DataContractSpecification;
13+
using Packata.DataContractSpecification.Serialization;
14+
using Packata.DataContractSpecification.Serialization.Yaml;
15+
using Packata.DataContractSpecification.ServerTypes;
16+
using Packata.DataContractSpecification.Testing.Serialization;
17+
18+
namespace Packata.DataContractSpecification.Testing.Serialization.Yaml;
19+
20+
public class DataContractSerializerTests : BaseDataContractSerializerTests
21+
{
22+
protected override IDataContractSerializer GetSerializer()
23+
=> new DataContractSerializer();
24+
25+
protected override string GetFormat() => "yaml";
26+
27+
[Test]
28+
public void Deserialize_CovidCases_AllFields()
29+
{
30+
string resourceName = $"{GetType().Namespace}.Resources.covid-cases.{GetFormat()}";
31+
using var stream = GetType().Assembly.GetManifestResourceStream(resourceName)
32+
?? throw new FileNotFoundException($"The embedded file {resourceName} doesn't exist.");
33+
34+
using var streamReader = new StreamReader(stream);
35+
var dataContract = GetSerializer().Deserialize(streamReader, Mock.Of<IDataPackageContainer>(), new StorageProvider());
36+
37+
Assert.That(dataContract, Is.Not.Null);
38+
39+
Assert.Multiple(() =>
40+
{
41+
Assert.That(dataContract.DataContractSpecification, Is.EqualTo("0.9.3"));
42+
Assert.That(dataContract.Id, Is.EqualTo("covid_cases"));
43+
44+
Assert.That(dataContract.Info, Is.Not.Null);
45+
Assert.That(dataContract.Info!.Title, Is.EqualTo("COVID-19 cases"));
46+
Assert.That(dataContract.Info.Description, Is.EqualTo("Johns Hopkins University Consolidated data on COVID-19 cases, sourced from Enigma"));
47+
Assert.That(dataContract.Info.Version, Is.EqualTo("0.0.1"));
48+
});
49+
50+
Assert.That(dataContract.Models, Is.Not.Null);
51+
Assert.That(dataContract.Models, Does.ContainKey("covid_cases"));
52+
53+
var model = dataContract.Models["covid_cases"];
54+
55+
Assert.Multiple(() =>
56+
{
57+
Assert.That(model.Description, Does.Contain("confirmed covid cases reported"));
58+
59+
Assert.That(model.Fields, Is.Not.Null);
60+
Assert.That(model.Fields["fips"].Type, Is.EqualTo("string"));
61+
Assert.That(model.Fields["fips"].Description, Does.Contain("state and county"));
62+
63+
Assert.That(model.Fields["admin2"].Type, Is.EqualTo("string"));
64+
Assert.That(model.Fields["province_state"].Type, Is.EqualTo("string"));
65+
Assert.That(model.Fields["country_region"].Type, Is.EqualTo("string"));
66+
67+
Assert.That(model.Fields["last_update"].Type, Is.EqualTo("timestamp_ntz"));
68+
Assert.That(model.Fields["latitude"].Type, Is.EqualTo("double"));
69+
Assert.That(model.Fields["longitude"].Type, Is.EqualTo("double"));
70+
Assert.That(model.Fields["confirmed"].Type, Is.EqualTo("int"));
71+
72+
Assert.That(model.Fields["combined_key"].Type, Is.EqualTo("string"));
73+
Assert.That(model.Fields["combined_key"].Description, Does.Contain("county name+state name+country name"));
74+
});
75+
76+
var servers = dataContract.Servers;
77+
78+
Assert.Multiple(() =>
79+
{
80+
Assert.That(servers.Count, Is.EqualTo(1));
81+
Assert.That(servers.Keys, Does.Contain("s3-json"));
82+
83+
Assert.That(servers["s3-json"].Type, Is.EqualTo("s3"));
84+
Assert.That(servers["s3-json"], Is.TypeOf<S3Server>());
85+
var s3Server = (S3Server)servers["s3-json"];
86+
Assert.That(s3Server.Location, Is.EqualTo("s3://covid19-lake/enigma-jhu/json/*.json"));
87+
Assert.That(s3Server.Format, Does.Contain("json"));
88+
Assert.That(s3Server.Delimiter, Is.EqualTo("new_line"));
89+
});
90+
}
91+
92+
[Test]
93+
public void Deserialize_OrdersLatestNested_AllFields()
94+
{
95+
string resourceName = $"{GetType().Namespace}.Resources.orders-latest-nested.{GetFormat()}";
96+
using var stream = GetType().Assembly.GetManifestResourceStream(resourceName)
97+
?? throw new FileNotFoundException($"The embedded file {resourceName} doesn't exist.");
98+
99+
using var streamReader = new StreamReader(stream);
100+
var dataContract = GetSerializer().Deserialize(streamReader, Mock.Of<IDataPackageContainer>(), new StorageProvider());
101+
102+
Assert.That(dataContract, Is.Not.Null);
103+
104+
Assert.Multiple(() =>
105+
{
106+
Assert.That(dataContract.DataContractSpecification, Is.EqualTo("0.9.3"));
107+
Assert.That(dataContract.Id, Is.EqualTo("urn:datacontract:checkout:orders-latest-nested"));
108+
109+
Assert.That(dataContract.Info, Is.Not.Null);
110+
Assert.That(dataContract.Info!.Title, Is.EqualTo("Orders Latest (Nested)"));
111+
Assert.That(dataContract.Info.Version, Is.EqualTo("1.0.0"));
112+
Assert.That(dataContract.Info.Description, Does.StartWith("Successful customer orders in the webshop"));
113+
Assert.That(dataContract.Info.Owner, Is.EqualTo("Checkout Team"));
114+
Assert.That(dataContract.Info.Contact, Is.Not.Null);
115+
Assert.That(dataContract.Info.Contact!.Name, Is.EqualTo("John Doe (Data Product Owner)"));
116+
Assert.That(dataContract.Info.Contact.Url, Is.EqualTo("https://teams.microsoft.com/l/channel/example/checkout"));
117+
118+
Assert.That(dataContract.Terms, Is.Not.Null);
119+
Assert.That(dataContract.Terms!.Usage, Does.Contain("analytics and machine learning"));
120+
Assert.That(dataContract.Terms.Limitations, Does.Contain("Not suitable for real-time"));
121+
Assert.That(dataContract.Terms.Billing, Is.EqualTo("5000 USD per month"));
122+
Assert.That(dataContract.Terms.NoticePeriod, Is.EqualTo("P3M"));
123+
});
124+
125+
Assert.Multiple(() =>
126+
{
127+
// orders model
128+
Assert.That(dataContract.Models, Does.ContainKey("orders"));
129+
var orders = dataContract.Models["orders"];
130+
Assert.That(orders.Description, Does.Contain("cancelled and deleted orders"));
131+
Assert.That(orders.Type, Is.EqualTo("table"));
132+
133+
Assert.That(orders.Fields["order_id"].Required, Is.True);
134+
Assert.That(orders.Fields["order_id"].Unique, Is.True);
135+
Assert.That(orders.Fields["order_id"].PrimaryKey, Is.True);
136+
137+
Assert.That(orders.Fields["order_timestamp"].Type, Is.EqualTo("timestamp"));
138+
Assert.That(orders.Fields["order_timestamp"].Required, Is.True);
139+
140+
Assert.That(orders.Fields["order_total"].Type, Is.EqualTo("long"));
141+
Assert.That(orders.Fields["order_total"].Required, Is.True);
142+
143+
Assert.That(orders.Fields["customer_id"].Type, Is.EqualTo("text"));
144+
Assert.That(orders.Fields["customer_id"].MinLength, Is.EqualTo(10));
145+
Assert.That(orders.Fields["customer_id"].MaxLength, Is.EqualTo(20));
146+
147+
Assert.That(orders.Fields["customer_email_address"].Format, Is.EqualTo("email"));
148+
Assert.That(orders.Fields["customer_email_address"].Required, Is.True);
149+
150+
var address = orders.Fields["address"];
151+
Assert.That(address.Type, Is.EqualTo("object"));
152+
Assert.That(address.Fields!["street"].Type, Is.EqualTo("text"));
153+
Assert.That(address.Fields["city"].Type, Is.EqualTo("text"));
154+
Assert.That(address.Fields["additional_lines"].Type, Is.EqualTo("array"));
155+
Assert.That(address.Fields["additional_lines"].Items!.Type, Is.EqualTo("text"));
156+
Assert.That(address.Fields["additional_lines"].Items!.Description, Is.EqualTo("Additional line"));
157+
158+
Assert.That(orders.Fields["processed_timestamp"].Required, Is.True);
159+
160+
// line_items model
161+
Assert.That(dataContract.Models, Does.ContainKey("line_items"));
162+
var lineItems = dataContract.Models["line_items"];
163+
Assert.That(lineItems.Description, Does.Contain("part of an order"));
164+
Assert.That(lineItems.Type, Is.EqualTo("table"));
165+
166+
Assert.That(lineItems.Fields["lines_item_id"].Type, Is.EqualTo("text"));
167+
Assert.That(lineItems.Fields["lines_item_id"].Required, Is.True);
168+
Assert.That(lineItems.Fields["lines_item_id"].Unique, Is.True);
169+
Assert.That(lineItems.Fields["lines_item_id"].PrimaryKey, Is.True);
170+
171+
Assert.That(lineItems.Fields["order_id"].References, Is.EqualTo("orders.order_id"));
172+
173+
Assert.That(lineItems.Fields["sku"].Description, Does.Contain("purchased article number"));
174+
});
175+
}
176+
177+
[Test]
178+
public void Deserialize_OrdersLatest_WithTermsAndPolicies()
179+
{
180+
string resourceName = $"{GetType().Namespace}.Resources.orders-latest.{GetFormat()}";
181+
using var stream = GetType().Assembly.GetManifestResourceStream(resourceName)
182+
?? throw new FileNotFoundException($"The embedded file {resourceName} doesn't exist.");
183+
184+
using var streamReader = new StreamReader(stream);
185+
var dataContract = GetSerializer().Deserialize(streamReader, Mock.Of<IDataPackageContainer>(), new StorageProvider());
186+
187+
Assert.That(dataContract, Is.Not.Null);
188+
189+
Assert.Multiple(() =>
190+
{
191+
// Top-level
192+
Assert.That(dataContract.DataContractSpecification, Is.EqualTo("1.1.0"));
193+
Assert.That(dataContract.Id, Is.EqualTo("urn:datacontract:checkout:orders-latest"));
194+
195+
// Info
196+
Assert.That(dataContract.Info, Is.Not.Null);
197+
Assert.That(dataContract.Info!.Title, Is.EqualTo("Orders Latest"));
198+
Assert.That(dataContract.Info.Version, Is.EqualTo("2.0.0"));
199+
Assert.That(dataContract.Info.Description, Does.Contain("Successful customer orders in the webshop"));
200+
Assert.That(dataContract.Info.Owner, Is.EqualTo("Checkout Team"));
201+
Assert.That(dataContract.Info.Contact, Is.Not.Null);
202+
Assert.That(dataContract.Info.Contact!.Name, Is.EqualTo("John Doe (Data Product Owner)"));
203+
Assert.That(dataContract.Info.Contact.Url, Is.EqualTo("https://teams.microsoft.com/l/channel/example/checkout"));
204+
205+
// Terms
206+
Assert.That(dataContract.Terms, Is.Not.Null);
207+
Assert.That(dataContract.Terms!.Usage, Does.Contain("analytics and machine learning"));
208+
Assert.That(dataContract.Terms.Limitations, Does.Contain("Data may not be used to identify individual customers"));
209+
Assert.That(dataContract.Terms.Billing, Is.EqualTo("5000 USD per month"));
210+
Assert.That(dataContract.Terms.NoticePeriod, Is.EqualTo("P3M"));
211+
212+
// Policies
213+
Assert.That(dataContract.Terms.Policies, Is.Not.Null.And.Count.EqualTo(2));
214+
Assert.That(dataContract.Terms.Policies[0].Type, Is.EqualTo("privacy-policy").IgnoreCase);
215+
Assert.That(dataContract.Terms.Policies[0].Url, Is.EqualTo("https://example.com/privacy-policy"));
216+
Assert.That(dataContract.Terms.Policies[1].Description, Is.EqualTo("External data is licensed under agreement 1234."));
217+
Assert.That(dataContract.Terms.Policies[1].Url, Is.EqualTo("https://example.com/license/1234"));
218+
});
219+
}
220+
221+
[Test]
222+
public void Deserialize_Servers_WithServers()
223+
{
224+
string resourceName = $"{GetType().Namespace}.Resources.servers.{GetFormat()}";
225+
using var stream = GetType().Assembly.GetManifestResourceStream(resourceName)
226+
?? throw new FileNotFoundException($"The embedded file {resourceName} doesn't exist.");
227+
228+
using var streamReader = new StreamReader(stream);
229+
var dataContract = GetSerializer().Deserialize(streamReader, Mock.Of<IDataPackageContainer>(), new StorageProvider());
230+
231+
Assert.That(dataContract, Is.Not.Null);
232+
var servers = dataContract.Servers;
233+
234+
Assert.Multiple(() =>
235+
{
236+
Assert.That(servers.Count, Is.EqualTo(3));
237+
238+
Assert.That(servers.Keys, Does.Contain("s3-csv"));
239+
Assert.That(servers["s3-csv"].Type, Is.EqualTo("s3"));
240+
Assert.That(servers["s3-csv"], Is.TypeOf<S3Server>());
241+
var s3Server = (S3Server)servers["s3-csv"];
242+
Assert.That(s3Server.Location, Is.EqualTo("s3://covid19-lake/enigma-jhu/csv/*.csv"));
243+
Assert.That(s3Server.Format, Is.EqualTo("csv"));
244+
245+
Assert.That(servers.Keys, Does.Contain("kafka-orders"));
246+
Assert.That(servers["kafka-orders"].Type, Is.EqualTo("kafka"));
247+
Assert.That(servers["kafka-orders"], Is.TypeOf<KafkaServer>());
248+
var kafkaServer = (KafkaServer)servers["kafka-orders"];
249+
Assert.That(kafkaServer.Host, Is.EqualTo("pkc-7xoy1.eu-central-1.aws.confluent.cloud:9092"));
250+
Assert.That(kafkaServer.Topic, Is.EqualTo("orders.v1"));
251+
Assert.That(kafkaServer.Format, Is.EqualTo("avro"));
252+
253+
Assert.That(servers.Keys, Does.Contain("pg-customers"));
254+
Assert.That(servers["pg-customers"].Type, Is.EqualTo("postgresql"));
255+
Assert.That(servers["pg-customers"], Is.TypeOf<PostgreSqlServer>());
256+
var pgCustomers = (PostgreSqlServer)servers["pg-customers"];
257+
Assert.That(pgCustomers.Host, Is.EqualTo("postgres.crm.2"));
258+
Assert.That(pgCustomers.Database, Is.EqualTo("crm"));
259+
Assert.That(pgCustomers.Schema, Is.EqualTo("main"));
260+
});
261+
}
262+
}

0 commit comments

Comments
 (0)