DatabaseTests.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.Common;
  4. using System.Data.SqlClient;
  5. using System.Dynamic;
  6. using Moq;
  7. using PetaPoco.Core;
  8. using PetaPoco.Providers;
  9. using PetaPoco.Tests.Unit.Models;
  10. using Shouldly;
  11. using Xunit;
  12. // ReSharper disable ObjectCreationAsStatement
  13. namespace PetaPoco.Tests.Unit
  14. {
  15. public class DatabaseTests
  16. {
  17. private readonly DbProviderFactory _dbProviderFactory = new Mock<DbProviderFactory>(MockBehavior.Strict).Object;
  18. private readonly IProvider _provider = new Mock<IProvider>(MockBehavior.Loose).Object;
  19. private IDatabase DB { get; }
  20. public DatabaseTests()
  21. => DB = new Database("cs", _provider);
  22. [Fact]
  23. public void Construct_GivenWrappedFactory_ShouldNotThrow()
  24. => new Database("some connection string", new DbProviderWrapper());
  25. [Fact]
  26. public void Construct_GivenUnwrappedFactory_ShouldNotThrow()
  27. => new Database("some connection string", SqlClientFactory.Instance);
  28. [Fact]
  29. public void Construct_GivenInvalidArguments_ShouldThrow()
  30. {
  31. #if !NETCOREAPP
  32. Should.Throw<InvalidOperationException>(() => new Database());
  33. #endif
  34. Should.Throw<ArgumentNullException>(() => new Database((DbConnection) null));
  35. Should.Throw<ArgumentNullException>(() => new Database("some connection string", (IProvider) null));
  36. Should.Throw<ArgumentException>(() => new Database(null, _provider));
  37. #if !NETCOREAPP
  38. Should.Throw<ArgumentException>(() => new Database((string) null));
  39. Should.Throw<InvalidOperationException>(() => new Database("connection string name"));
  40. #endif
  41. Should.Throw<ArgumentException>(() => new Database("connection string", (string) null));
  42. Should.Throw<ArgumentException>(() => new Database("connection string", ""));
  43. Should.Throw<ArgumentException>(() => new Database(null, "provider name"));
  44. Should.Throw<ArgumentException>(() => new Database("", "provider name"));
  45. Should.Throw<ArgumentException>(() => new Database("connection string", "provider name"));
  46. Should.Throw<ArgumentException>(() => new Database(null, _dbProviderFactory));
  47. Should.Throw<ArgumentNullException>(() => new Database("some connection string", (DbProviderFactory) null));
  48. Should.Throw<ArgumentNullException>(() => new Database((IDatabaseBuildConfiguration) null));
  49. Should.Throw<InvalidOperationException>(() =>
  50. {
  51. try
  52. {
  53. DatabaseConfiguration.Build().Create();
  54. }
  55. catch (Exception e)
  56. {
  57. #if !NETCOREAPP
  58. e.Message.ShouldContain("One or more connection strings");
  59. #else
  60. e.Message.ShouldContain("A connection string is required");
  61. #endif
  62. throw;
  63. }
  64. });
  65. Should.Throw<InvalidOperationException>(() =>
  66. {
  67. try
  68. {
  69. DatabaseConfiguration.Build().UsingConnectionString("cs").Create();
  70. }
  71. catch (Exception e)
  72. {
  73. e.Message.ShouldContain("Unable to locate a provider");
  74. throw;
  75. }
  76. });
  77. Should.Throw<ArgumentException>(() => new Database<SqlServerDatabaseProvider>(null));
  78. }
  79. [Fact]
  80. public void Update_GivenInvalidArguments_ShouldThrow()
  81. {
  82. Should.Throw<ArgumentNullException>(() => DB.Update(null, "primaryKeyName", new Person(), 1));
  83. Should.Throw<ArgumentNullException>(() => DB.Update("tableName", null, new Person(), 1));
  84. Should.Throw<ArgumentNullException>(() => DB.Update("tableName", "primaryKeyName", null, 1));
  85. Should.Throw<ArgumentNullException>(() => DB.Update(null, "primaryKeyName", new Person(), 1, null));
  86. Should.Throw<ArgumentNullException>(() => DB.Update("tableName", null, new Person(), 1, null));
  87. Should.Throw<ArgumentNullException>(() => DB.Update("tableName", "primaryKeyName", null, 1, null));
  88. Should.Throw<ArgumentNullException>(() => DB.Update(null, "primaryKeyName", new Person()));
  89. Should.Throw<ArgumentNullException>(() => DB.Update("tableName", null, new Person()));
  90. Should.Throw<ArgumentNullException>(() => DB.Update("tableName", "primaryKeyName", (Person) null));
  91. Should.Throw<ArgumentNullException>(() => DB.Update(null, "primaryKeyName", new Person(), null));
  92. Should.Throw<ArgumentNullException>(() => DB.Update("tableName", null, new Person(), null));
  93. Should.Throw<ArgumentNullException>(() => DB.Update("tableName", "primaryKeyName", null, null));
  94. Should.Throw<ArgumentNullException>(() => DB.Update(null, null));
  95. Should.Throw<ArgumentNullException>(() => DB.Update(null));
  96. Should.Throw<ArgumentNullException>(() => DB.Update(null, (object) null));
  97. Should.Throw<ArgumentNullException>(() => DB.Update(null, (object) null, null));
  98. Should.Throw<ArgumentNullException>(() => DB.Update<Person>((string) null));
  99. Should.Throw<ArgumentNullException>(() => DB.Update<Person>((Sql) null));
  100. }
  101. [Fact]
  102. public void Update_GivenPocoAndEmptyColumns_ShouldReturn_Zero()
  103. {
  104. var person = new Person() { Id = Guid.NewGuid() };
  105. var columns = new List<string>();
  106. var output = DB.Update(person, columns);
  107. output.ShouldBe(0);
  108. }
  109. [Fact]
  110. public void Update_GivenTableNameAndEmptyColumns_ShouldReturn_Zero()
  111. {
  112. var person = new Person() { Id = Guid.NewGuid() };
  113. var columns = new List<string>();
  114. var output = DB.Update("person", "id", person, columns);
  115. output.ShouldBe(0);
  116. }
  117. [Fact]
  118. public void Insert_GivenInvalidArguments_ShouldThrow()
  119. {
  120. Should.Throw<ArgumentNullException>(() => DB.Insert(null));
  121. Should.Throw<ArgumentNullException>(() => DB.Insert(null, null));
  122. Should.Throw<ArgumentNullException>(() => DB.Insert(null, "SomeColumn", new Person()));
  123. Should.Throw<ArgumentNullException>(() => DB.Insert("SomeTable", null, new Person()));
  124. Should.Throw<ArgumentNullException>(() => DB.Insert("SomeTable", "SomeColumn", null));
  125. }
  126. [Fact]
  127. public void IsNew_GivenInvalidArguments_ShouldThrow()
  128. {
  129. Should.Throw<ArgumentNullException>(() => DB.IsNew(null));
  130. Should.Throw<ArgumentNullException>(() => DB.IsNew(null, null));
  131. Should.Throw<ArgumentException>(() => DB.IsNew("MissingId", new { }));
  132. Should.Throw<InvalidOperationException>(() => DB.IsNew(new TransactionLog()));
  133. Should.Throw<InvalidOperationException>(() => DB.IsNew(new EntityWithoutConventionId()));
  134. Should.Throw<InvalidOperationException>(() => DB.IsNew(new ExpandoObject()));
  135. }
  136. [Fact]
  137. public void IsNew_GivenTransientEntity_ShoudlBeTrue()
  138. {
  139. DB.IsNew(new GenericIdEntity<Guid>()).ShouldBeTrue();
  140. DB.IsNew(new GenericIdEntity<Guid?>()).ShouldBeTrue();
  141. DB.IsNew(new GenericIdEntity<int>()).ShouldBeTrue();
  142. DB.IsNew(new GenericIdEntity<uint>()).ShouldBeTrue();
  143. DB.IsNew(new GenericIdEntity<short>()).ShouldBeTrue();
  144. DB.IsNew(new GenericIdEntity<ushort>()).ShouldBeTrue();
  145. DB.IsNew(new GenericIdEntity<long>()).ShouldBeTrue();
  146. DB.IsNew(new GenericIdEntity<ulong>()).ShouldBeTrue();
  147. DB.IsNew(new GenericIdEntity<string>()).ShouldBeTrue();
  148. DB.IsNew(new GenericIdEntity<ComplexPrimaryKey>()).ShouldBeTrue();
  149. DB.IsNew(new GenericIdEntity<decimal>()).ShouldBeTrue();
  150. }
  151. [Fact]
  152. public void IsNew_GivenNonTransientEntity_ShouldBeFalse()
  153. {
  154. DB.IsNew(new GenericIdEntity<Guid> { Id = Guid.Parse("803A25C4-65D9-4F92-9305-0854FD134841") }).ShouldBeFalse();
  155. DB.IsNew(new GenericIdEntity<Guid?> { Id = Guid.Parse("803A25C4-65D9-4F92-9305-0854FD134841") }).ShouldBeFalse();
  156. DB.IsNew(new GenericIdEntity<int> { Id = 1 }).ShouldBeFalse();
  157. DB.IsNew(new GenericIdEntity<uint> { Id = 1 }).ShouldBeFalse();
  158. DB.IsNew(new GenericIdEntity<short> { Id = 1 }).ShouldBeFalse();
  159. DB.IsNew(new GenericIdEntity<ushort> { Id = 1 }).ShouldBeFalse();
  160. DB.IsNew(new GenericIdEntity<long> { Id = 1 }).ShouldBeFalse();
  161. DB.IsNew(new GenericIdEntity<ulong> { Id = 1 }).ShouldBeFalse();
  162. DB.IsNew(new GenericIdEntity<string> { Id = "ID-1" }).ShouldBeFalse();
  163. DB.IsNew(new GenericIdEntity<ComplexPrimaryKey> { Id = new ComplexPrimaryKey() }).ShouldBeFalse();
  164. DB.IsNew(new GenericIdEntity<decimal> { Id = 1.0M }).ShouldBeFalse();
  165. }
  166. [Fact]
  167. public void IsNew_GivenTransientEntityAndPrimaryKeyName_ShouldBeTrue()
  168. {
  169. DB.IsNew("Id", new GenericNoMapsIdEntity<Guid>()).ShouldBeTrue();
  170. DB.IsNew("Id", new GenericNoMapsIdEntity<Guid?>()).ShouldBeTrue();
  171. DB.IsNew("Id", new GenericNoMapsIdEntity<int>()).ShouldBeTrue();
  172. DB.IsNew("Id", new GenericNoMapsIdEntity<uint>()).ShouldBeTrue();
  173. DB.IsNew("Id", new GenericNoMapsIdEntity<short>()).ShouldBeTrue();
  174. DB.IsNew("Id", new GenericNoMapsIdEntity<ushort>()).ShouldBeTrue();
  175. DB.IsNew("Id", new GenericNoMapsIdEntity<long>()).ShouldBeTrue();
  176. DB.IsNew("Id", new GenericNoMapsIdEntity<ulong>()).ShouldBeTrue();
  177. DB.IsNew("Id", new GenericNoMapsIdEntity<string>()).ShouldBeTrue();
  178. DB.IsNew("Id", new GenericNoMapsIdEntity<ComplexPrimaryKey>()).ShouldBeTrue();
  179. DB.IsNew("Id", new GenericNoMapsIdEntity<decimal>()).ShouldBeTrue();
  180. }
  181. [Fact]
  182. public void IsNew_GivenNonTransientEntityAndPrimaryKeyName_ShouldBeFalse()
  183. {
  184. DB.IsNew("id", new GenericNoMapsIdEntity<Guid> { Id = Guid.Parse("803A25C4-65D9-4F92-9305-0854FD134841") }).ShouldBeFalse();
  185. DB.IsNew("id", new GenericNoMapsIdEntity<Guid?> { Id = Guid.Parse("803A25C4-65D9-4F92-9305-0854FD134841") }).ShouldBeFalse();
  186. DB.IsNew("id", new GenericNoMapsIdEntity<int> { Id = 1 }).ShouldBeFalse();
  187. DB.IsNew("id", new GenericNoMapsIdEntity<uint> { Id = 1 }).ShouldBeFalse();
  188. DB.IsNew("id", new GenericNoMapsIdEntity<short> { Id = 1 }).ShouldBeFalse();
  189. DB.IsNew("id", new GenericNoMapsIdEntity<ushort> { Id = 1 }).ShouldBeFalse();
  190. DB.IsNew("id", new GenericNoMapsIdEntity<long> { Id = 1 }).ShouldBeFalse();
  191. DB.IsNew("id", new GenericNoMapsIdEntity<ulong> { Id = 1 }).ShouldBeFalse();
  192. DB.IsNew("id", new GenericNoMapsIdEntity<string> { Id = "ID-1" }).ShouldBeFalse();
  193. DB.IsNew("id", new GenericNoMapsIdEntity<ComplexPrimaryKey> { Id = new ComplexPrimaryKey() }).ShouldBeFalse();
  194. DB.IsNew("id", new GenericNoMapsIdEntity<decimal> { Id = 1.0M }).ShouldBeFalse();
  195. }
  196. // ReSharper disable MemberCanBePrivate.Global
  197. // ReSharper disable UnusedAutoPropertyAccessor.Global
  198. // ReSharper disable UnusedMember.Global
  199. [ExplicitColumns]
  200. [TableName("Orders")]
  201. [PrimaryKey("Id")]
  202. public class GenericIdEntity<T>
  203. {
  204. [Column]
  205. public T Id { get; set; }
  206. }
  207. public class GenericNoMapsIdEntity<T>
  208. {
  209. public T Id { get; set; }
  210. }
  211. public class ComplexPrimaryKey
  212. {
  213. }
  214. public class EntityWithoutConventionId
  215. {
  216. public int SomeOtherId { get; set; }
  217. public DateTime CreatedOn { get; set; }
  218. public string Text { get; set; }
  219. }
  220. public class DbProviderWrapper : DbProviderFactory, IServiceProvider
  221. {
  222. public object GetService(Type serviceType)
  223. {
  224. if (serviceType == typeof(DbProviderWrapper))
  225. return SqlClientFactory.Instance;
  226. return null;
  227. }
  228. }
  229. // ReSharper restore UnusedMember.Global
  230. // ReSharper restore UnusedAutoPropertyAccessor.Global
  231. // ReSharper restore MemberCanBePrivate.Global
  232. }
  233. }