PageRenderTime 44ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/Tests/TechTalk.SpecFlow.RuntimeTests/AssistTests/CreateInstanceHelperMethodTests.cs

http://github.com/techtalk/SpecFlow
C# | 523 lines | 408 code | 114 blank | 1 comment | 0 complexity | 0ef60116fdd771079ec82cc3feb0d1d7 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0
  1. using System;
  2. using System.Globalization;
  3. using System.Threading;
  4. using Xunit;
  5. using FluentAssertions;
  6. using TechTalk.SpecFlow.Assist;
  7. using TechTalk.SpecFlow.Assist.Attributes;
  8. using TechTalk.SpecFlow.RuntimeTests.AssistTests.ExampleEntities;
  9. namespace TechTalk.SpecFlow.RuntimeTests.AssistTests
  10. {
  11. public class CreateInstanceHelperMethodTests
  12. {
  13. public CreateInstanceHelperMethodTests()
  14. {
  15. // this is required, because the tests depend on parsing decimals with the en-US culture
  16. Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", false);
  17. }
  18. [Fact]
  19. public void Create_instance_will_return_an_instance_of_T()
  20. {
  21. var table = new Table("Field", "Value");
  22. var person = table.CreateInstance<Person>();
  23. person.Should().NotBeNull();
  24. }
  25. [Fact]
  26. public void Create_instance_will_set_values_with_a_vertical_table_when_there_is_one_row_and_one_column()
  27. {
  28. var table = new Table("FirstName");
  29. table.AddRow("Howard");
  30. var person = table.CreateInstance<Person>();
  31. person.FirstName.Should().Be("Howard");
  32. }
  33. [Fact]
  34. public void Create_instance_will_set_values_with_a_vertical_table_and_unbound_column_throws_ColumnCouldNotBeBoundException_on_verify()
  35. {
  36. var table = new Table("FirstNaame");
  37. table.AddRow("Howard");
  38. Action act = () => table.CreateInstance<Person>(new InstanceCreationOptions() { VerifyAllColumnsBound = true });
  39. act.Should().Throw<ColumnCouldNotBeBoundException>();
  40. }
  41. [Fact]
  42. public void When_one_row_exists_with_two_headers_and_the_first_row_value_is_not_a_property_then_treat_as_horizontal_table()
  43. {
  44. var table = new Table("AnotherValue", "YetAnotherValue");
  45. table.AddRow("x", "y");
  46. var test = table.CreateInstance<TestingVerticalTable>();
  47. test.AnotherValue.Should().Be("x");
  48. test.YetAnotherValue.Should().Be("y");
  49. }
  50. [Fact]
  51. public void When_one_row_exists_with_two_headers_and_the_first_row_value_is_a_property_then_treat_as_a_vertical_table()
  52. {
  53. var table = new Table("AnotherValue", "YetAnotherValue");
  54. table.AddRow("AnotherValue", "applesauce");
  55. var test = table.CreateInstance<TestingVerticalTable>();
  56. test.AnotherValue.Should().Be("applesauce");
  57. test.YetAnotherValue.Should().Be(null);
  58. }
  59. [Fact]
  60. public void When_one_row_exists_with_two_headers_and_the_first_row_value_is_a_property_without_perfect_name_match_then_treat_as_a_vertical_table()
  61. {
  62. var table = new Table("AnotherValue", "YetAnotherValue");
  63. table.AddRow("Another value", "applesauce");
  64. var test = table.CreateInstance<TestingVerticalTable>();
  65. test.AnotherValue.Should().Be("applesauce");
  66. test.YetAnotherValue.Should().Be(null);
  67. }
  68. [Fact]
  69. public void When_one_row_exists_with_three_headers_then_treat_as_horizontal_table()
  70. {
  71. var table = new Table("Field", "Value", "AnotherValue");
  72. table.AddRow("one", "two", "three");
  73. var test = table.CreateInstance<TestingVerticalTable>();
  74. test.Field.Should().Be("one");
  75. test.Value.Should().Be("two");
  76. test.AnotherValue.Should().Be("three");
  77. }
  78. public class TestingVerticalTable
  79. {
  80. public string Field { get; set; }
  81. public string Value { get; set; }
  82. public string AnotherValue { get; set; }
  83. public string YetAnotherValue { get; set; }
  84. }
  85. [Fact]
  86. public void Sets_string_values()
  87. {
  88. var table = new Table("Field", "Value");
  89. table.AddRow("FirstName", "John");
  90. table.AddRow("LastName", "Galt");
  91. var person = table.CreateInstance<Person>();
  92. person.FirstName.Should().Be("John");
  93. person.LastName.Should().Be("Galt");
  94. }
  95. [Fact]
  96. public void Sets_string_values_unbound_column_throws_ColumnCouldNotBeBoundException_on_verify()
  97. {
  98. var table = new Table("Field", "Value");
  99. table.AddRow("FirstNaame", "John");
  100. table.AddRow("LastName", "Galt");
  101. Action act = () => table.CreateInstance<Person>(new InstanceCreationOptions { VerifyAllColumnsBound = true });
  102. act.Should().Throw<ColumnCouldNotBeBoundException>();
  103. }
  104. [Fact]
  105. public void SetConstructor_unbound_column_throws_ColumnCouldNotBeBoundException_on_verify()
  106. {
  107. var table = new Table("Field", "Value");
  108. table.AddRow("FirstNaame", "John");
  109. table.AddRow("LastName", "Galt");
  110. Action act = () => table.CreateInstance<PersonWithMandatoryLastName>(new InstanceCreationOptions { VerifyAllColumnsBound = true });
  111. act.Should().Throw<ColumnCouldNotBeBoundException>();
  112. }
  113. [Fact]
  114. public void Sets_int_values()
  115. {
  116. var table = new Table("Field", "Value");
  117. table.AddRow("NumberOfIdeas", "3");
  118. var person = table.CreateInstance<Person>();
  119. person.NumberOfIdeas.Should().Be(3);
  120. }
  121. [Fact]
  122. public void Sets_nullable_int_values()
  123. {
  124. var table = new Table("Field", "Value");
  125. table.AddRow("NullableInt", "9");
  126. var person = table.CreateInstance<Person>();
  127. person.NullableInt.Should().Be(9);
  128. }
  129. [Fact]
  130. public void Sets_uint_values()
  131. {
  132. var table = new Table("Field", "Value");
  133. table.AddRow("UnsignedInt", "3");
  134. var person = table.CreateInstance<Person>();
  135. person.UnsignedInt.Should().Be(3);
  136. }
  137. [Fact]
  138. public void Sets_nullable_uint_values()
  139. {
  140. var table = new Table("Field", "Value");
  141. table.AddRow("NullableUnsignedInt", "9");
  142. var person = table.CreateInstance<Person>();
  143. person.NullableUnsignedInt.Should().Be((uint?)9);
  144. }
  145. [Fact]
  146. public void Sets_decimal_values()
  147. {
  148. var table = new Table("Field", "Value");
  149. table.AddRow("Salary", "9.78");
  150. var person = table.CreateInstance<Person>();
  151. person.Salary.Should().Be(9.78M);
  152. }
  153. [Fact]
  154. public void Sets_nullable_decimal_values()
  155. {
  156. var table = new Table("Field", "Value");
  157. table.AddRow("NullableDecimal", "19.78");
  158. var person = table.CreateInstance<Person>();
  159. person.NullableDecimal.Should().Be(19.78M);
  160. }
  161. [Fact]
  162. public void Sets_bool_values()
  163. {
  164. var table = new Table("Field", "Value");
  165. table.AddRow("IsRational", "true");
  166. var person = table.CreateInstance<Person>();
  167. person.IsRational.Should().BeTrue();
  168. }
  169. [Fact]
  170. public void Sets_nullable_bool_values()
  171. {
  172. var table = new Table("Field", "Value");
  173. table.AddRow("NullableBool", "true");
  174. var person = table.CreateInstance<Person>();
  175. person.NullableBool.Should().Be(true);
  176. }
  177. [Fact]
  178. public void Sets_datetime_values()
  179. {
  180. var table = new Table("Field", "Value");
  181. table.AddRow("BirthDate", "12/31/2010");
  182. var person = table.CreateInstance<Person>();
  183. person.BirthDate.Should().Be(new DateTime(2010, 12, 31));
  184. }
  185. [Fact]
  186. public void Sets_nullable_datetime_values()
  187. {
  188. var table = new Table("Field", "Value");
  189. table.AddRow("NullableDateTime", "11/30/2010");
  190. var person = table.CreateInstance<Person>();
  191. person.NullableDateTime.Should().Be(new DateTime(2010, 11, 30));
  192. }
  193. [Fact]
  194. public void Sets_double_values()
  195. {
  196. var table = new Table("Field", "Value");
  197. table.AddRow("Double", "4.235");
  198. var person = table.CreateInstance<Person>();
  199. person.Double.Should().Be(4.235);
  200. }
  201. [Fact]
  202. public void Sets_nullable_double_values()
  203. {
  204. var table = new Table("Field", "Value");
  205. table.AddRow("NullableDouble", "7.218");
  206. var person = table.CreateInstance<Person>();
  207. person.NullableDouble.Should().Be(7.218);
  208. }
  209. [Fact]
  210. public void Sets_Guid_values()
  211. {
  212. var table = new Table("Field", "Value");
  213. table.AddRow("GuidId", "B48D8AF4-405F-4286-B83E-774EA773CFA3");
  214. var person = table.CreateInstance<Person>();
  215. person.GuidId.Should().Be(new Guid("B48D8AF4-405F-4286-B83E-774EA773CFA3"));
  216. }
  217. [Fact]
  218. public void Sets_nullable_guid_values()
  219. {
  220. var table = new Table("Field", "Value");
  221. table.AddRow("NullableGuidId", "B48D8AF4-405F-4286-B83E-774EA773CFA3");
  222. var person = table.CreateInstance<Person>();
  223. person.NullableGuidId.Should().Be(new Guid("B48D8AF4-405F-4286-B83E-774EA773CFA3"));
  224. }
  225. [Fact]
  226. public void Sets_float_values()
  227. {
  228. var table = new Table("Field", "Value");
  229. table.AddRow("Float", "98.22");
  230. var person = table.CreateInstance<Person>();
  231. person.Float.Should().Be(98.22F);
  232. }
  233. [Fact]
  234. public void Sets_nullable_float_values()
  235. {
  236. var table = new Table("Field", "Value");
  237. table.AddRow("NullableFloat", "55.66");
  238. var person = table.CreateInstance<Person>();
  239. person.NullableFloat.Should().Be(55.66F);
  240. }
  241. [Fact]
  242. public void Ignores_spaces_when_matching_enum_property_name()
  243. {
  244. var table = new Table("Field", "Value");
  245. table.AddRow("This Is A Style", "Soft");
  246. var test = table.CreateInstance<EnumPropertyTest>();
  247. test.ThisIsAStyle.Should().Be(Style.Soft);
  248. }
  249. [Fact]
  250. public void Ignores_casing_when_matching_enum_property_name()
  251. {
  252. var table = new Table("Field", "Value");
  253. table.AddRow("ThisisaSTYLE", "VeryCool");
  254. var test = table.CreateInstance<EnumPropertyTest>();
  255. test.ThisIsAStyle.Should().Be(Style.VeryCool);
  256. }
  257. private class EnumPropertyTest
  258. {
  259. public Style ThisIsAStyle { get; set; }
  260. }
  261. [Fact]
  262. public void Replaces_special_characters_when_matching_property_names()
  263. {
  264. var table = new Table("Field", "Value");
  265. table.AddRow("Prop.1", "hello");
  266. table.AddRow("Prop.2", "world");
  267. var test = table.CreateInstance<Prop>();
  268. test.Prop1.Should().Be("hello");
  269. test.Prop2.Should().Be("world");
  270. }
  271. [Fact]
  272. public void Works_with_snake_case()
  273. {
  274. var table = new Table("Field", "Value");
  275. table.AddRow("Look at me", "hello");
  276. table.AddRow("This is so long", "world");
  277. var test = table.CreateInstance<Snake>();
  278. test.Look_at_me.Should().Be("hello");
  279. test.this_is_so_long.Should().Be("world");
  280. }
  281. [Fact]
  282. public void Works_with_tuples()
  283. {
  284. var table = new Table("PropertyOne", "PropertyTwo", "PropertyThree");
  285. table.AddRow("Look at me", "hello", "999");
  286. var test = table.CreateInstance<(string one, string two, int three)>();
  287. test.one.Should().Be("Look at me");
  288. test.two.Should().Be("hello");
  289. test.three.Should().Be(999);
  290. }
  291. [Fact]
  292. public void Too_long_tuples_throw_exception()
  293. {
  294. var table = new Table("PropertyOne", "PropertyTwo", "PropertyThree", "PropertyFour", "PropertyFive", "PropertySix", "PropertySeven", "PropertyEight");
  295. table.AddRow("Look at me", "hello", "999", "this", "should", "actually", "fail", "right?");
  296. Assert.Throws<Exception>(() => table.CreateInstance<(string one, string two, int three, string four, string five, string six, string seven, string eight)>());
  297. }
  298. [Fact]
  299. public void Works_with_tuples_vertical_format()
  300. {
  301. var table = new Table("Field", "Value");
  302. table.AddRow("One", "hello");
  303. table.AddRow("Two", "world");
  304. table.AddRow("Three", "999");
  305. var test = table.CreateInstance<(string one, string two, int three)>();
  306. test.one.Should().Be("hello");
  307. test.two.Should().Be("world");
  308. test.three.Should().Be(999);
  309. }
  310. [Fact]
  311. public void Uses_property_aliases()
  312. {
  313. var table = new Table("AliasOne", "AliasTwo", "AliasThree");
  314. table.AddRow("PropertyOne", "PropertyTwo", "PropertyThree");
  315. var test = table.CreateInstance<AliasedClass>();
  316. test.PropertyOne.Should().Be("PropertyOne");
  317. test.PropertyTwo.Should().Be("PropertyTwo");
  318. test.PropertyThree.Should().Be("PropertyThree");
  319. }
  320. [Fact]
  321. public void Uses_field_aliases()
  322. {
  323. var table = new Table("FieldAliasOne", "FieldAliasTwo", "FieldAliasThree");
  324. table.AddRow("FieldOne", "FieldTwo", "FieldThree");
  325. var test = table.CreateInstance<AliasedClass>();
  326. test.FieldOne.Should().Be("FieldOne");
  327. test.FieldTwo.Should().Be("FieldTwo");
  328. test.FieldThree.Should().Be("FieldThree");
  329. }
  330. [Fact]
  331. public void Property_aliases_allow_multiple_property_population()
  332. {
  333. var table = new Table("AliasOne", "AliasTwo", "AliasThree");
  334. table.AddRow("PropertyOne", "PropertyTwo", "PropertyThree");
  335. var test = table.CreateInstance<AliasedClass>();
  336. test.PropertyOne.Should().Be("PropertyOne");
  337. test.AnotherPropertyWithSameAlias.Should().Be("PropertyOne");
  338. }
  339. [Fact]
  340. public void Property_aliases_do_not_allow_type_mismatch_property_population()
  341. {
  342. var table = new Table("AliasOne", "AliasTwo", "AliasThree");
  343. table.AddRow("PropertyOne", "PropertyTwo", "PropertyThree");
  344. var test = table.CreateInstance<AliasedClass>();
  345. test.PropertyOne.Should().Be("PropertyOne");
  346. test.AliasedButTypeMismatch.Should().Be(0);
  347. }
  348. [Fact]
  349. public void Property_aliases_work_for_vertical_format()
  350. {
  351. var table = new Table("Field", "Value");
  352. table.AddRow("Alias One", "Hello");
  353. table.AddRow("AliasTwo", "World");
  354. table.AddRow("AliasThree", "From Rich");
  355. var test = table.CreateInstance<AliasedClass>();
  356. test.PropertyOne.Should().Be("Hello");
  357. test.PropertyTwo.Should().Be("World");
  358. test.PropertyThree.Should().Be("From Rich");
  359. }
  360. [Theory]
  361. [InlineData("FirstName", "MiddleName", "Surname")]
  362. [InlineData("FirstName", "MiddleName", "Lastname")]
  363. [InlineData("First Name", "Middle Name", "Last name")]
  364. [InlineData("Known As", "Never Known As", "Dad's Last Name")]
  365. public void Property_can_have_many_aliases_and_uses_regex_to_match_business_jargon(string firstNameAlias, string middleNameAlias, string lastNameAlias)
  366. {
  367. var table = new Table("Field", "Value");
  368. table.AddRow(firstNameAlias, "Richard");
  369. table.AddRow(middleNameAlias, "David");
  370. table.AddRow(lastNameAlias, "Linnell");
  371. var test = table.CreateInstance<AliasedClass>();
  372. test.PropertyOne.Should().Be("Richard");
  373. test.PropertyTwo.Should().Be("David");
  374. test.PropertyThree.Should().Be("Linnell");
  375. }
  376. private class Prop
  377. {
  378. public string Prop1 { get; set; }
  379. public string Prop2 { get; set; }
  380. }
  381. private class Snake
  382. {
  383. public string Look_at_me { get; set; }
  384. public string this_is_so_long { get; set; }
  385. }
  386. private class AliasedClass
  387. {
  388. [TableAliases("Alias[ ]*One", "First[ ]?Name", "^Known As$")]
  389. public string PropertyOne { get; set; }
  390. [TableAliases("Alias[ ]*Two", "Middle[ ]?Name", "^Never Known As$")]
  391. public string PropertyTwo { get; set; }
  392. [TableAliases("AliasThree")]
  393. [TableAliases("Surname")]
  394. [TableAliases("Last[ ]?name")]
  395. [TableAliases("Dad's Last Name")]
  396. public string PropertyThree { get; set; }
  397. [TableAliases("FieldAliasOne")]
  398. public string FieldOne;
  399. [TableAliases("FieldAliasTwo")]
  400. public string FieldTwo;
  401. [TableAliases("FieldAliasThree")]
  402. public string FieldThree;
  403. [TableAliases("AliasOne")]
  404. public string AnotherPropertyWithSameAlias { get; set; }
  405. [TableAliases("AliasOne")]
  406. public long AliasedButTypeMismatch { get; set; }
  407. }
  408. }
  409. }