• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

fluentassertions / fluentassertions.datasets / 13245501597

10 Feb 2025 04:22PM UTC coverage: 94.362% (+0.3%) from 94.089%
13245501597

Pull #24

github

web-flow
Bump Verify.Xunit from 28.9.0 to 28.10.1 in the xunit group

Bumps the xunit group with 1 update: [Verify.Xunit](https://github.com/VerifyTests/Verify).


Updates `Verify.Xunit` from 28.9.0 to 28.10.1
- [Release notes](https://github.com/VerifyTests/Verify/releases)
- [Commits](https://github.com/VerifyTests/Verify/compare/28.9.0...28.10.1)

---
updated-dependencies:
- dependency-name: Verify.Xunit
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: xunit
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #24: Bump Verify.Xunit from 28.9.0 to 28.10.1 in the xunit group

458 of 498 branches covered (91.97%)

Branch coverage included in aggregate %.

1266 of 1329 relevant lines covered (95.26%)

2324.28 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.02
/Src/FluentAssertions.DataSets/Equivalency/ConstraintEquivalencyStep.cs
1
using System.Collections.Generic;
2
using System.Data;
3
using System.Diagnostics.CodeAnalysis;
4
using System.Linq;
5
using System.Text;
6
using FluentAssertions.DataSets.Common;
7
using FluentAssertions.Equivalency;
8
using FluentAssertions.Execution;
9

10
namespace FluentAssertions.DataSets.Equivalency;
11

12
public class ConstraintEquivalencyStep : EquivalencyStep<Constraint>
13
{
14
    protected override EquivalencyResult OnHandle(Comparands comparands, IEquivalencyValidationContext context,
15
        IValidateChildNodeEquivalency nestedValidator)
16
    {
17
        var assertionChain = AssertionChain.GetOrCreate().For(context);
1,964✔
18

19
        if (comparands.Subject is not Constraint)
1,964!
20
        {
21
            assertionChain
×
22
                .FailWith("Expected {context:constraint} to be a value of type Constraint, but found {0}",
×
23
                    comparands.Subject.GetType());
×
24
        }
25
        else
26
        {
27
            var subject = (Constraint)comparands.Subject;
1,964✔
28
            var expectation = (Constraint)comparands.Expectation;
1,964✔
29

30
            var selectedMembers = GetMembersFromExpectation(comparands, context.CurrentNode, context.Options)
1,964✔
31
                .ToDictionary(member => member.Expectation.Name);
14,272✔
32

33
            CompareCommonProperties(context, nestedValidator, context.Options, subject, expectation, selectedMembers, assertionChain);
1,964✔
34

35
            bool matchingType = subject.GetType() == expectation.GetType();
1,964✔
36

37
            assertionChain
1,964✔
38
                .ForCondition(matchingType)
1,964✔
39
                .FailWith("Expected {context:constraint} to be of type {0}, but found {1}", expectation.GetType(),
1,964✔
40
                    subject.GetType());
1,964✔
41

42
            if (matchingType)
1,964✔
43
            {
44
                if (subject is UniqueConstraint subjectUniqueConstraint
1,964✔
45
                    && expectation is UniqueConstraint expectationUniqueConstraint)
1,964✔
46
                {
47
                    CompareConstraints(nestedValidator, context, subjectUniqueConstraint, expectationUniqueConstraint,
1,340✔
48
                        selectedMembers, assertionChain);
1,340✔
49
                }
50
                else if (subject is ForeignKeyConstraint subjectForeignKeyConstraint
624!
51
                         && expectation is ForeignKeyConstraint expectationForeignKeyConstraint)
624✔
52
                {
53
                    CompareConstraints(nestedValidator, context, subjectForeignKeyConstraint, expectationForeignKeyConstraint,
624✔
54
                        selectedMembers, assertionChain);
624✔
55
                }
56
                else
57
                {
58
                    assertionChain
×
59
                        .FailWith("Don't know how to handle {constraint:a Constraint} of type {0}", subject.GetType());
×
60
                }
61
            }
62
        }
63

64
        return EquivalencyResult.EquivalencyProven;
1,964✔
65
    }
66

67
    private static void CompareCommonProperties(IEquivalencyValidationContext context, IValidateChildNodeEquivalency parent,
68
        IEquivalencyOptions options, Constraint subject, Constraint expectation,
69
        Dictionary<string, IMember> selectedMembers, AssertionChain assertionChain)
70
    {
71
        if (selectedMembers.ContainsKey("ConstraintName"))
1,964✔
72
        {
73
            assertionChain
1,964✔
74
                .ForCondition(subject.ConstraintName == expectation.ConstraintName)
1,964✔
75
                .FailWith("Expected {context:constraint} to have a ConstraintName of {0}{reason}, but found {1}",
1,964✔
76
                    expectation.ConstraintName, subject.ConstraintName);
1,964✔
77
        }
78

79
        if (selectedMembers.ContainsKey("Table"))
1,964✔
80
        {
81
            assertionChain
1,956✔
82
                .ForCondition(subject.Table.TableName == expectation.Table.TableName)
1,956✔
83
                .FailWith(
1,956✔
84
                    "Expected {context:constraint} to be associated with a Table with TableName of {0}{reason}, but found {1}",
1,956✔
85
                    expectation.Table.TableName, subject.Table.TableName);
1,956✔
86
        }
87

88
        if (selectedMembers.TryGetValue("ExtendedProperties", out IMember expectationMember))
1,964✔
89
        {
90
            IMember matchingMember = FindMatchFor(expectationMember, context.CurrentNode, subject, options, assertionChain);
1,964✔
91

92
            if (matchingMember is not null)
1,964✔
93
            {
94
                var nestedComparands = new Comparands
1,964✔
95
                {
1,964✔
96
                    Subject = matchingMember.GetValue(subject),
1,964✔
97
                    Expectation = expectationMember.GetValue(expectation),
1,964✔
98
                    CompileTimeType = expectationMember.Type
1,964✔
99
                };
1,964✔
100

101
                parent.AssertEquivalencyOf(nestedComparands, context.AsNestedMember(expectationMember));
1,964✔
102
            }
103
        }
104
    }
1,964✔
105

106
    private static void CompareConstraints(IValidateChildNodeEquivalency parent, IEquivalencyValidationContext context,
107
        UniqueConstraint subject, UniqueConstraint expectation, Dictionary<string, IMember> selectedMembers, AssertionChain assertionChain)
108
    {
109
        assertionChain
1,340✔
110
            .ForCondition(subject.ConstraintName == expectation.ConstraintName)
1,340✔
111
            .FailWith("Expected {context:constraint} to be named {0}{reason}, but found {1}", expectation.ConstraintName,
1,340✔
112
                subject.ConstraintName);
1,340✔
113

114
        var nestedMember = MemberFactory.Create(
1,340✔
115
            typeof(Constraint).GetProperty(nameof(subject.ExtendedProperties)),
1,340✔
116
            context.CurrentNode);
1,340✔
117

118
        var nestedComparands = new Comparands
1,340✔
119
        {
1,340✔
120
            Subject = nestedMember.GetValue(subject),
1,340✔
121
            Expectation = nestedMember.GetValue(expectation),
1,340✔
122
            CompileTimeType = nestedMember.Type
1,340✔
123
        };
1,340✔
124

125
        parent.AssertEquivalencyOf(nestedComparands, context.AsNestedMember(nestedMember));
1,340✔
126

127
        if (selectedMembers.ContainsKey(nameof(expectation.IsPrimaryKey)))
1,340✔
128
        {
129
            assertionChain
1,340✔
130
                .ForCondition(subject.IsPrimaryKey == expectation.IsPrimaryKey)
1,340✔
131
                .FailWith("Expected {context:constraint} to be a {0} constraint{reason}, but found a {1} constraint",
1,340✔
132
                    expectation.IsPrimaryKey ? "Primary Key" : "Foreign Key",
1,340✔
133
                    subject.IsPrimaryKey ? "Primary Key" : "Foreign Key");
1,340✔
134
        }
135

136
        if (selectedMembers.ContainsKey(nameof(expectation.Columns)))
1,340✔
137
        {
138
            CompareConstraintColumns(subject.Columns, expectation.Columns, assertionChain);
1,340✔
139
        }
140
    }
1,340✔
141

142
    [SuppressMessage("Design", "MA0051:Method is too long", Justification = "Needs to be refactored")]
143
    private static void CompareConstraints(IValidateChildNodeEquivalency parent, IEquivalencyValidationContext context,
144
        ForeignKeyConstraint subject, ForeignKeyConstraint expectation, Dictionary<string, IMember> selectedMembers, AssertionChain assertionChain)
145
    {
146
        assertionChain
624✔
147
            .ForCondition(subject.ConstraintName == expectation.ConstraintName)
624✔
148
            .FailWith("Expected {context:constraint} to be named {0}{reason}, but found {1}", expectation.ConstraintName,
624✔
149
                subject.ConstraintName);
624✔
150

151
        var nestedMember = MemberFactory.Create(
624✔
152
            typeof(Constraint).GetProperty(nameof(subject.ExtendedProperties)),
624✔
153
            context.CurrentNode);
624✔
154

155
        var nestedComparands = new Comparands
624✔
156
        {
624✔
157
            Subject = nestedMember.GetValue(subject),
624✔
158
            Expectation = nestedMember.GetValue(expectation),
624✔
159
            CompileTimeType = nestedMember.Type
624✔
160
        };
624✔
161

162
        parent.AssertEquivalencyOf(nestedComparands, context.AsNestedMember(nestedMember));
624✔
163

164
        if (selectedMembers.ContainsKey(nameof(expectation.RelatedTable)))
624✔
165
        {
166
            assertionChain
624✔
167
                .ForCondition(subject.RelatedTable.TableName == expectation.RelatedTable.TableName)
624✔
168
                .FailWith("Expected {context:constraint} to have a related table named {0}{reason}, but found {1}",
624✔
169
                    expectation.RelatedTable.TableName, subject.RelatedTable.TableName);
624✔
170
        }
171

172
        if (selectedMembers.ContainsKey(nameof(expectation.AcceptRejectRule)))
624✔
173
        {
174
            assertionChain
624✔
175
                .ForCondition(subject.AcceptRejectRule == expectation.AcceptRejectRule)
624✔
176
                .FailWith(
624✔
177
                    "Expected {context:constraint} to have AcceptRejectRule.{0}{reason}, but found AcceptRejectRule.{1}",
624✔
178
                    expectation.AcceptRejectRule, subject.AcceptRejectRule);
624✔
179
        }
180

181
        if (selectedMembers.ContainsKey(nameof(expectation.DeleteRule)))
624✔
182
        {
183
            assertionChain
624✔
184
                .ForCondition(subject.DeleteRule == expectation.DeleteRule)
624✔
185
                .FailWith("Expected {context:constraint} to have DeleteRule Rule.{0}{reason}, but found Rule.{1}",
624✔
186
                    expectation.DeleteRule, subject.DeleteRule);
624✔
187
        }
188

189
        if (selectedMembers.ContainsKey(nameof(expectation.UpdateRule)))
624✔
190
        {
191
            assertionChain
624✔
192
                .ForCondition(subject.UpdateRule == expectation.UpdateRule)
624✔
193
                .FailWith("Expected {context:constraint} to have UpdateRule Rule.{0}{reason}, but found Rule.{1}",
624✔
194
                    expectation.UpdateRule, subject.UpdateRule);
624✔
195
        }
196

197
        if (selectedMembers.ContainsKey(nameof(expectation.Columns)))
624✔
198
        {
199
            CompareConstraintColumns(subject.Columns, expectation.Columns, assertionChain);
624✔
200
        }
201

202
        if (selectedMembers.ContainsKey(nameof(expectation.RelatedColumns)))
624✔
203
        {
204
            CompareConstraintColumns(subject.RelatedColumns, expectation.RelatedColumns, assertionChain);
624✔
205
        }
206
    }
624✔
207

208
    private static void CompareConstraintColumns(DataColumn[] subjectColumns, DataColumn[] expectationColumns, AssertionChain assertionChain)
209
    {
210
        var subjectColumnNames = new HashSet<string>(subjectColumns.Select(col => col.ColumnName));
5,190✔
211
        var expectationColumnNames = new HashSet<string>(expectationColumns.Select(col => col.ColumnName));
5,190✔
212

213
        var missingColumnNames = expectationColumnNames.Except(subjectColumnNames).ToList();
2,588✔
214
        var extraColumnNames = subjectColumnNames.Except(expectationColumnNames).ToList();
2,588✔
215

216
        var failureMessage = new StringBuilder();
2,588✔
217

218
        if (missingColumnNames.Count > 0)
2,588✔
219
        {
220
            failureMessage.Append("Expected {context:constraint} to include ");
10✔
221

222
            if (missingColumnNames.Count == 1)
10✔
223
            {
224
                failureMessage.Append("column ").Append(missingColumnNames.Single());
8✔
225
            }
226
            else
227
            {
228
                failureMessage.Append("columns ").Append(missingColumnNames.JoinUsingWritingStyle());
2✔
229
            }
230

231
            failureMessage
10✔
232
                .Append("{reason}, but constraint does not include ")
10✔
233
                .Append(missingColumnNames.Count == 1
10✔
234
                    ? "that column. "
10✔
235
                    : "these columns. ");
10✔
236
        }
237

238
        if (extraColumnNames.Count > 0)
2,588✔
239
        {
240
            failureMessage.Append("Did not expect {context:constraint} to include ");
10✔
241

242
            if (extraColumnNames.Count == 1)
10✔
243
            {
244
                failureMessage.Append("column ").Append(extraColumnNames.Single());
8✔
245
            }
246
            else
247
            {
248
                failureMessage.Append("columns ").Append(extraColumnNames.JoinUsingWritingStyle());
2✔
249
            }
250

251
            failureMessage.Append("{reason}, but it does.");
10✔
252
        }
253

254
        bool successful = failureMessage.Length == 0;
2,588✔
255

256
        assertionChain
2,588✔
257
            .ForCondition(successful)
2,588✔
258
            .FailWith(failureMessage.ToString());
2,588✔
259
    }
2,588✔
260

261
    private static IMember FindMatchFor(IMember selectedMemberInfo, INode currentNode, object subject,
262
        IEquivalencyOptions config, AssertionChain assertionChain)
263
    {
264
        IEnumerable<IMember> query =
1,964✔
265
            from rule in config.MatchingRules
1,964✔
266
            let match = rule.Match(selectedMemberInfo, subject, currentNode, config, assertionChain)
1,964✔
267
            where match is not null
1,964✔
268
            select match;
3,928✔
269

270
        return query.FirstOrDefault();
1,964✔
271
    }
272

273
    private static IEnumerable<IMember> GetMembersFromExpectation(Comparands comparands, INode currentNode,
274
        IEquivalencyOptions options)
275
    {
276
        IEnumerable<IMember> members = Enumerable.Empty<IMember>();
1,964✔
277

278
        foreach (IMemberSelectionRule rule in options.SelectionRules)
14,692✔
279
        {
280
            // Within a ConstraintCollection, different types of Constraint are kept polymorphically.
281
            // As such, the concept of "compile-time type" isn't meaningful, and we override this
282
            // with the discovered type of the constraint at runtime.
283
            members = rule.SelectMembers(currentNode, members,
5,382✔
284
                new MemberSelectionContext(comparands.RuntimeType, comparands.RuntimeType, options));
5,382✔
285
        }
286

287
        return members;
1,964✔
288
    }
289
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc