Skip to content

Commit b11826d

Browse files
committed
CSHARP-1723: Improve error messages and add more tests.
1 parent 843f075 commit b11826d

File tree

4 files changed

+184
-7
lines changed

4 files changed

+184
-7
lines changed

src/MongoDB.Bson/Serialization/BsonCreatorMap.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ public void Freeze()
122122
{
123123
if (_arguments.Count != expectedArgumentsCount)
124124
{
125-
throw new BsonSerializationException("Creator map must have the right number of arguments configured.");
125+
throw new BsonSerializationException($"Creator map for class {_classMap.ClassType.FullName} has {expectedArgumentsCount} arguments, not {_arguments.Count}.");
126126
}
127127

128128
foreach (var argument in _arguments)
@@ -144,7 +144,7 @@ public void Freeze()
144144
{
145145
if (expectedArgumentsCount != 0)
146146
{
147-
throw new BsonSerializationException("Creator map must have arguments configured.");
147+
throw new BsonSerializationException($"Creator map for class {_classMap.ClassType.FullName} has {expectedArgumentsCount} arguments, but none are configured.");
148148
}
149149
}
150150

@@ -182,7 +182,7 @@ public BsonCreatorMap SetArguments(IEnumerable<MemberInfo> arguments)
182182
var expectedArgumentsCount = GetExpectedArgumentsCount();
183183
if (argumentsList.Count != expectedArgumentsCount)
184184
{
185-
throw new ArgumentException("Wrong number of arguments provided", nameof(arguments));
185+
throw new ArgumentException($"Creator map for class {_classMap.ClassType.FullName} has {expectedArgumentsCount} arguments, not {argumentsList.Count}.", nameof(arguments));
186186
}
187187

188188
_arguments = argumentsList;

tests/MongoDB.Bson.Tests/MongoDB.Bson.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@
157157
<Compile Include="Serialization\Conventions\MemberNameElementNameConventionsTests.cs" />
158158
<Compile Include="Serialization\Conventions\NamedExtraElementsConventionsTests.cs" />
159159
<Compile Include="Serialization\Conventions\NamedIdConventionsTests.cs" />
160+
<Compile Include="Serialization\Conventions\NamedParameterCreatorMapConventionTests.cs" />
160161
<Compile Include="Serialization\Conventions\ReadWriteMemberFinderConventionsTests.cs" />
161162
<Compile Include="Serialization\Conventions\StandardDiscriminatorConventionTests.cs" />
162163
<Compile Include="Serialization\Conventions\StringObjectIdGeneratorConventionsTests.cs" />

tests/MongoDB.Bson.Tests/Serialization/Attributes/BsonConstructorAttributeTests.cs

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,72 @@
2626

2727
namespace MongoDB.Bson.Tests.Serialization.Attributes
2828
{
29-
public class BsonConstructorWithNoNamesProvidedTests
29+
public class BsonConstructorAttributeWhenArgumentNamesProvidedTests
30+
{
31+
[Fact]
32+
public void constructor_with_int_should_be_mapped_correctly()
33+
{
34+
var classMap = BsonClassMap.LookupClassMap(typeof(C));
35+
36+
var constructorInfo = typeof(C).GetTypeInfo().GetConstructor(new[] { typeof(int) });
37+
var creatorMap = classMap.CreatorMaps.Where(c => c.MemberInfo == constructorInfo).SingleOrDefault();
38+
creatorMap.Should().NotBeNull();
39+
var expectedArguments = new[]
40+
{
41+
typeof(C).GetTypeInfo().GetProperty("X")
42+
};
43+
creatorMap.Arguments.Should().Equal(expectedArguments);
44+
}
45+
46+
[Fact]
47+
public void constructor_with_int_and_string_should_be_mapped_correctly()
48+
{
49+
var classMap = BsonClassMap.LookupClassMap(typeof(C));
50+
51+
var constructorInfo = typeof(C).GetTypeInfo().GetConstructor(new[] { typeof(int), typeof(string) });
52+
var creatorMap = classMap.CreatorMaps.Where(c => c.MemberInfo == constructorInfo).SingleOrDefault();
53+
creatorMap.Should().NotBeNull();
54+
var expectedArguments = new[]
55+
{
56+
typeof(C).GetTypeInfo().GetProperty("X"),
57+
typeof(C).GetTypeInfo().GetProperty("Y")
58+
};
59+
creatorMap.Arguments.Should().Equal(expectedArguments);
60+
}
61+
62+
[Fact]
63+
public void constructor_with_string_should_be_mapped_correctly()
64+
{
65+
var classMap = BsonClassMap.LookupClassMap(typeof(C));
66+
67+
var constructorInfo = typeof(C).GetTypeInfo().GetConstructor(new[] { typeof(string) });
68+
var creatorMap = classMap.CreatorMaps.Where(c => c.MemberInfo == constructorInfo).SingleOrDefault();
69+
creatorMap.Should().NotBeNull();
70+
var expectedArguments = new[]
71+
{
72+
typeof(C).GetTypeInfo().GetProperty("Y")
73+
};
74+
creatorMap.Arguments.Should().Equal(expectedArguments);
75+
}
76+
77+
// nested types
78+
private class C
79+
{
80+
[BsonConstructor("X")]
81+
public C(int a) { }
82+
83+
[BsonConstructor("Y")]
84+
public C(string b) { }
85+
86+
[BsonConstructor("X", "Y")]
87+
public C(int a, string b) { }
88+
89+
public int X { get; private set; }
90+
public string Y { get; private set; }
91+
}
92+
}
93+
94+
public class BsonConstructorAttributeWhenArgumentNamesNotProvidedTests
3095
{
3196
[Fact]
3297
public void constructor_with_int_should_be_mapped_correctly()
@@ -91,7 +156,7 @@ public C(int x, string y) { }
91156
}
92157
}
93158

94-
public class BsonConstructorAttributeWhenArgumentNameDoesNotExistTests
159+
public class BsonConstructorAttributeWhenArgumentNameDoesNotMatchAnyMemberTests
95160
{
96161
[Fact]
97162
public void Apply_should_throw()
@@ -113,7 +178,7 @@ public C(int y)
113178
}
114179
}
115180

116-
public class BsonConstructorAttributeWhenParameterNameDoesNotExistTests
181+
public class BsonConstructorAttributeWhenArgumentNamesNotProvidedAndConstructorParameterNameDoesNotMatchAnyMemberTests
117182
{
118183
[Fact]
119184
public void Apply_should_throw()
@@ -135,7 +200,7 @@ public C(int x)
135200
}
136201
}
137202

138-
public class BsonConstructorAttributeWhenArgumentsCountIsWrongTests
203+
public class BsonConstructorAttributeWhenArgumentNamesCountIsWrongTests
139204
{
140205
[Fact]
141206
public void Apply_should_throw()
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/* Copyright 2016 MongoDB Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
using System;
17+
using System.Linq;
18+
using System.Reflection;
19+
using FluentAssertions;
20+
using MongoDB.Bson.Serialization;
21+
using MongoDB.Bson.Serialization.Conventions;
22+
using Xunit;
23+
24+
namespace MongoDB.Bson.Tests.Serialization.Conventions
25+
{
26+
public class NamedParameterCreatorMapConventionTests
27+
{
28+
[Fact]
29+
public void Apply_should_do_nothing_when_creator_map_already_has_arguments_configured()
30+
{
31+
var subject = new NamedParameterCreatorMapConvention();
32+
var classMap = new BsonClassMap<C>();
33+
var constructorInfo = typeof(C).GetTypeInfo().GetConstructor(new[] { typeof(int) });
34+
var creatorMap = classMap.MapConstructor(constructorInfo, "Y");
35+
var originalArguments = creatorMap.Arguments;
36+
37+
subject.Apply(creatorMap);
38+
39+
creatorMap.Arguments.Should().BeSameAs(originalArguments);
40+
}
41+
42+
[Fact]
43+
public void Apply_should_do_nothing_when_member_info_is_null()
44+
{
45+
var subject = new NamedParameterCreatorMapConvention();
46+
var classMap = new BsonClassMap<C>();
47+
var @delegate = (Func<int, C>)(y => new C(y));
48+
var creatorMap = classMap.MapCreator(@delegate);
49+
creatorMap.Arguments.Should().BeNull();
50+
creatorMap.MemberInfo.Should().BeNull();
51+
52+
subject.Apply(creatorMap);
53+
54+
creatorMap.Arguments.Should().BeNull();
55+
}
56+
57+
[Fact]
58+
public void Apply_should_do_nothing_when_constructor_parameter_name_does_not_match_any_property_or_field()
59+
{
60+
var subject = new NamedParameterCreatorMapConvention();
61+
var classMap = new BsonClassMap<C>();
62+
var constructorInfo = typeof(C).GetTypeInfo().GetConstructor(new[] { typeof(int) });
63+
var creatorMap = classMap.MapConstructor(constructorInfo);
64+
creatorMap.Arguments.Should().BeNull();
65+
66+
subject.Apply(creatorMap);
67+
68+
creatorMap.Arguments.Should().BeNull();
69+
}
70+
71+
[Fact]
72+
public void Apply_should_set_arguments_when_constructor_parameter_names_match_a_field()
73+
{
74+
var subject = new NamedParameterCreatorMapConvention();
75+
var classMap = new BsonClassMap<C>();
76+
var constructorInfo = typeof(C).GetTypeInfo().GetConstructor(new[] { typeof(long) });
77+
var creatorMap = classMap.MapConstructor(constructorInfo);
78+
creatorMap.Arguments.Should().BeNull();
79+
80+
subject.Apply(creatorMap);
81+
82+
creatorMap.Arguments.Cast<FieldInfo>().Select(p => p.Name).Should().Equal(new[] { "F" });
83+
}
84+
85+
[Fact]
86+
public void Apply_should_set_arguments_when_constructor_parameter_names_match_a_property()
87+
{
88+
var subject = new NamedParameterCreatorMapConvention();
89+
var classMap = new BsonClassMap<C>();
90+
var constructorInfo = typeof(C).GetTypeInfo().GetConstructor(new[] { typeof(string) });
91+
var creatorMap = classMap.MapConstructor(constructorInfo);
92+
creatorMap.Arguments.Should().BeNull();
93+
94+
subject.Apply(creatorMap);
95+
96+
creatorMap.Arguments.Cast<PropertyInfo>().Select(p => p.Name).Should().Equal(new[] { "P" });
97+
}
98+
99+
// nested types
100+
private class C
101+
{
102+
public C(int x) { }
103+
public C(long f) { }
104+
public C(string p) { }
105+
106+
public int Y { get; set; }
107+
public long F = 0;
108+
public string P { get; set; }
109+
}
110+
}
111+
}

0 commit comments

Comments
 (0)