using System; using System.Collections.Generic; using System.Data.Common; using System.Data.SqlClient; using System.Dynamic; using Moq; using PetaPoco.Core; using PetaPoco.Providers; using PetaPoco.Tests.Unit.Models; using Shouldly; using Xunit; // ReSharper disable ObjectCreationAsStatement namespace PetaPoco.Tests.Unit { public class DatabaseTests { private readonly DbProviderFactory _dbProviderFactory = new Mock(MockBehavior.Strict).Object; private readonly IProvider _provider = new Mock(MockBehavior.Loose).Object; private IDatabase DB { get; } public DatabaseTests() => DB = new Database("cs", _provider); [Fact] public void Construct_GivenWrappedFactory_ShouldNotThrow() => new Database("some connection string", new DbProviderWrapper()); [Fact] public void Construct_GivenUnwrappedFactory_ShouldNotThrow() => new Database("some connection string", SqlClientFactory.Instance); [Fact] public void Construct_GivenInvalidArguments_ShouldThrow() { #if !NETCOREAPP Should.Throw(() => new Database()); #endif Should.Throw(() => new Database((DbConnection) null)); Should.Throw(() => new Database("some connection string", (IProvider) null)); Should.Throw(() => new Database(null, _provider)); #if !NETCOREAPP Should.Throw(() => new Database((string) null)); Should.Throw(() => new Database("connection string name")); #endif Should.Throw(() => new Database("connection string", (string) null)); Should.Throw(() => new Database("connection string", "")); Should.Throw(() => new Database(null, "provider name")); Should.Throw(() => new Database("", "provider name")); Should.Throw(() => new Database("connection string", "provider name")); Should.Throw(() => new Database(null, _dbProviderFactory)); Should.Throw(() => new Database("some connection string", (DbProviderFactory) null)); Should.Throw(() => new Database((IDatabaseBuildConfiguration) null)); Should.Throw(() => { try { DatabaseConfiguration.Build().Create(); } catch (Exception e) { #if !NETCOREAPP e.Message.ShouldContain("One or more connection strings"); #else e.Message.ShouldContain("A connection string is required"); #endif throw; } }); Should.Throw(() => { try { DatabaseConfiguration.Build().UsingConnectionString("cs").Create(); } catch (Exception e) { e.Message.ShouldContain("Unable to locate a provider"); throw; } }); Should.Throw(() => new Database(null)); } [Fact] public void Update_GivenInvalidArguments_ShouldThrow() { Should.Throw(() => DB.Update(null, "primaryKeyName", new Person(), 1)); Should.Throw(() => DB.Update("tableName", null, new Person(), 1)); Should.Throw(() => DB.Update("tableName", "primaryKeyName", null, 1)); Should.Throw(() => DB.Update(null, "primaryKeyName", new Person(), 1, null)); Should.Throw(() => DB.Update("tableName", null, new Person(), 1, null)); Should.Throw(() => DB.Update("tableName", "primaryKeyName", null, 1, null)); Should.Throw(() => DB.Update(null, "primaryKeyName", new Person())); Should.Throw(() => DB.Update("tableName", null, new Person())); Should.Throw(() => DB.Update("tableName", "primaryKeyName", (Person) null)); Should.Throw(() => DB.Update(null, "primaryKeyName", new Person(), null)); Should.Throw(() => DB.Update("tableName", null, new Person(), null)); Should.Throw(() => DB.Update("tableName", "primaryKeyName", null, null)); Should.Throw(() => DB.Update(null, null)); Should.Throw(() => DB.Update(null)); Should.Throw(() => DB.Update(null, (object) null)); Should.Throw(() => DB.Update(null, (object) null, null)); Should.Throw(() => DB.Update((string) null)); Should.Throw(() => DB.Update((Sql) null)); } [Fact] public void Update_GivenPocoAndEmptyColumns_ShouldReturn_Zero() { var person = new Person() { Id = Guid.NewGuid() }; var columns = new List(); var output = DB.Update(person, columns); output.ShouldBe(0); } [Fact] public void Update_GivenTableNameAndEmptyColumns_ShouldReturn_Zero() { var person = new Person() { Id = Guid.NewGuid() }; var columns = new List(); var output = DB.Update("person", "id", person, columns); output.ShouldBe(0); } [Fact] public void Insert_GivenInvalidArguments_ShouldThrow() { Should.Throw(() => DB.Insert(null)); Should.Throw(() => DB.Insert(null, null)); Should.Throw(() => DB.Insert(null, "SomeColumn", new Person())); Should.Throw(() => DB.Insert("SomeTable", null, new Person())); Should.Throw(() => DB.Insert("SomeTable", "SomeColumn", null)); } [Fact] public void IsNew_GivenInvalidArguments_ShouldThrow() { Should.Throw(() => DB.IsNew(null)); Should.Throw(() => DB.IsNew(null, null)); Should.Throw(() => DB.IsNew("MissingId", new { })); Should.Throw(() => DB.IsNew(new TransactionLog())); Should.Throw(() => DB.IsNew(new EntityWithoutConventionId())); Should.Throw(() => DB.IsNew(new ExpandoObject())); } [Fact] public void IsNew_GivenTransientEntity_ShoudlBeTrue() { DB.IsNew(new GenericIdEntity()).ShouldBeTrue(); DB.IsNew(new GenericIdEntity()).ShouldBeTrue(); DB.IsNew(new GenericIdEntity()).ShouldBeTrue(); DB.IsNew(new GenericIdEntity()).ShouldBeTrue(); DB.IsNew(new GenericIdEntity()).ShouldBeTrue(); DB.IsNew(new GenericIdEntity()).ShouldBeTrue(); DB.IsNew(new GenericIdEntity()).ShouldBeTrue(); DB.IsNew(new GenericIdEntity()).ShouldBeTrue(); DB.IsNew(new GenericIdEntity()).ShouldBeTrue(); DB.IsNew(new GenericIdEntity()).ShouldBeTrue(); DB.IsNew(new GenericIdEntity()).ShouldBeTrue(); } [Fact] public void IsNew_GivenNonTransientEntity_ShouldBeFalse() { DB.IsNew(new GenericIdEntity { Id = Guid.Parse("803A25C4-65D9-4F92-9305-0854FD134841") }).ShouldBeFalse(); DB.IsNew(new GenericIdEntity { Id = Guid.Parse("803A25C4-65D9-4F92-9305-0854FD134841") }).ShouldBeFalse(); DB.IsNew(new GenericIdEntity { Id = 1 }).ShouldBeFalse(); DB.IsNew(new GenericIdEntity { Id = 1 }).ShouldBeFalse(); DB.IsNew(new GenericIdEntity { Id = 1 }).ShouldBeFalse(); DB.IsNew(new GenericIdEntity { Id = 1 }).ShouldBeFalse(); DB.IsNew(new GenericIdEntity { Id = 1 }).ShouldBeFalse(); DB.IsNew(new GenericIdEntity { Id = 1 }).ShouldBeFalse(); DB.IsNew(new GenericIdEntity { Id = "ID-1" }).ShouldBeFalse(); DB.IsNew(new GenericIdEntity { Id = new ComplexPrimaryKey() }).ShouldBeFalse(); DB.IsNew(new GenericIdEntity { Id = 1.0M }).ShouldBeFalse(); } [Fact] public void IsNew_GivenTransientEntityAndPrimaryKeyName_ShouldBeTrue() { DB.IsNew("Id", new GenericNoMapsIdEntity()).ShouldBeTrue(); DB.IsNew("Id", new GenericNoMapsIdEntity()).ShouldBeTrue(); DB.IsNew("Id", new GenericNoMapsIdEntity()).ShouldBeTrue(); DB.IsNew("Id", new GenericNoMapsIdEntity()).ShouldBeTrue(); DB.IsNew("Id", new GenericNoMapsIdEntity()).ShouldBeTrue(); DB.IsNew("Id", new GenericNoMapsIdEntity()).ShouldBeTrue(); DB.IsNew("Id", new GenericNoMapsIdEntity()).ShouldBeTrue(); DB.IsNew("Id", new GenericNoMapsIdEntity()).ShouldBeTrue(); DB.IsNew("Id", new GenericNoMapsIdEntity()).ShouldBeTrue(); DB.IsNew("Id", new GenericNoMapsIdEntity()).ShouldBeTrue(); DB.IsNew("Id", new GenericNoMapsIdEntity()).ShouldBeTrue(); } [Fact] public void IsNew_GivenNonTransientEntityAndPrimaryKeyName_ShouldBeFalse() { DB.IsNew("id", new GenericNoMapsIdEntity { Id = Guid.Parse("803A25C4-65D9-4F92-9305-0854FD134841") }).ShouldBeFalse(); DB.IsNew("id", new GenericNoMapsIdEntity { Id = Guid.Parse("803A25C4-65D9-4F92-9305-0854FD134841") }).ShouldBeFalse(); DB.IsNew("id", new GenericNoMapsIdEntity { Id = 1 }).ShouldBeFalse(); DB.IsNew("id", new GenericNoMapsIdEntity { Id = 1 }).ShouldBeFalse(); DB.IsNew("id", new GenericNoMapsIdEntity { Id = 1 }).ShouldBeFalse(); DB.IsNew("id", new GenericNoMapsIdEntity { Id = 1 }).ShouldBeFalse(); DB.IsNew("id", new GenericNoMapsIdEntity { Id = 1 }).ShouldBeFalse(); DB.IsNew("id", new GenericNoMapsIdEntity { Id = 1 }).ShouldBeFalse(); DB.IsNew("id", new GenericNoMapsIdEntity { Id = "ID-1" }).ShouldBeFalse(); DB.IsNew("id", new GenericNoMapsIdEntity { Id = new ComplexPrimaryKey() }).ShouldBeFalse(); DB.IsNew("id", new GenericNoMapsIdEntity { Id = 1.0M }).ShouldBeFalse(); } // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global // ReSharper disable UnusedMember.Global [ExplicitColumns] [TableName("Orders")] [PrimaryKey("Id")] public class GenericIdEntity { [Column] public T Id { get; set; } } public class GenericNoMapsIdEntity { public T Id { get; set; } } public class ComplexPrimaryKey { } public class EntityWithoutConventionId { public int SomeOtherId { get; set; } public DateTime CreatedOn { get; set; } public string Text { get; set; } } public class DbProviderWrapper : DbProviderFactory, IServiceProvider { public object GetService(Type serviceType) { if (serviceType == typeof(DbProviderWrapper)) return SqlClientFactory.Instance; return null; } } // ReSharper restore UnusedMember.Global // ReSharper restore UnusedAutoPropertyAccessor.Global // ReSharper restore MemberCanBePrivate.Global } }