Skip to content

Commit

Permalink
add unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Fazzani committed May 19, 2020
1 parent 0f2df3f commit 5badc8f
Show file tree
Hide file tree
Showing 12 changed files with 376 additions and 21 deletions.
16 changes: 14 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Build
name: Build and test

on:
push:
Expand All @@ -12,12 +12,24 @@ on:
jobs:
build:
runs-on: ubuntu-18.04
name: Build solution
name: Build and test
steps:

- name: Checkout repository
uses: actions/checkout@v2

- name: Build with dotnet
run: dotnet build --configuration Release
shell: bash

- name: Install EF core tool
run: dotnet tool install --global dotnet-ef
shell: bash

- name: Run postgres database for testing
run: make setup_db_for_test
shell: bash

- name: Unit tests
run: dotnet test --no-restore --verbosity normal
shell: bash
23 changes: 23 additions & 0 deletions EF.Extensions.PgCopy.Tests/DbContext/Blog.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace EF.Extensions.PgCopy.Tests.DbContext
{
[Table("blog", Schema = "public")]
public class Blog
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column("id")]
public int Id { get; set; }

[Column("url")] public string Url { get; set; }

[Column("creation_datetime", TypeName = "timestamptz")]
public DateTime CreationDateTime { get; set; } = DateTime.Now;

public List<Post> Posts { get; set; }
}
}
29 changes: 29 additions & 0 deletions EF.Extensions.PgCopy.Tests/DbContext/BloggingContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using Microsoft.EntityFrameworkCore;

namespace EF.Extensions.PgCopy.Tests.DbContext
{
public class BloggingContext : Microsoft.EntityFrameworkCore.DbContext
{
private const string ConnectionString = "Host=localhost;Port=54322;Database=dbtest;Username=db_user;Password=dtpass";

public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }

public BloggingContext(DbContextOptions<BloggingContext> options)
: base(options)
{
}

public BloggingContext()
{

}

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseNpgsql(ConnectionString, opt =>
opt.CommandTimeout((int) TimeSpan.FromMinutes(1).TotalSeconds));
}
}
}
26 changes: 26 additions & 0 deletions EF.Extensions.PgCopy.Tests/DbContext/Post.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace EF.Extensions.PgCopy.Tests.DbContext
{
[Table("post", Schema = "public")]
public class Post
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column("id")]
public int Id { get; set; }

[Column("title")] public string Title { get; set; }
[Column("content")] public string Content { get; set; }
[Column("blog_id")] public int? BlogId { get; set; }
[Column("post_date")] public DateTime PostDate { get; set; }
[Column("online"), Required] public bool Online { get; set; }

[Column("creation_datetime", TypeName = "timestamptz")]
public DateTime CreationDateTime { get; set; } = DateTime.Now;

public Blog Blog { get; set; }
}
}
20 changes: 20 additions & 0 deletions EF.Extensions.PgCopy.Tests/EF.Extensions.PgCopy.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
<PackageReference Include="coverlet.collector" Version="1.2.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\EF.Extensions.PgCopy\EF.Extensions.PgCopy.csproj" />
</ItemGroup>

</Project>
127 changes: 127 additions & 0 deletions EF.Extensions.PgCopy.Tests/EfCopyTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using EF.Extensions.PgCopy.Tests.DbContext;
using Microsoft.EntityFrameworkCore;
using Xunit;

namespace EF.Extensions.PgCopy.Tests
{
public class EfCopyTest : IDisposable
{
public static readonly string ConnectionString =
"Host=localhost;Port=54322;Database=dbtest;Username=db_user;Password=dtpass";

private BloggingContext _dbContext;

public EfCopyTest()
{
var options = new DbContextOptionsBuilder<BloggingContext>()
.UseNpgsql(ConnectionString, opt => opt.CommandTimeout((int) TimeSpan.FromMinutes(1).TotalSeconds))
.Options;

_dbContext = new BloggingContext(options);
}

[Fact]
public void SaveCopyTest()
{
var posts = GeneratePosts();
var blogs = GenerateBlogs();
_dbContext.Posts.AddRange(posts);
_dbContext.Blogs.AddRange(blogs);

_dbContext.SaveByCopyChanges();

var blogs_count = _dbContext.Blogs.Count();
var posts_count = _dbContext.Posts.Count();

Assert.Equal(blogs.Count(), blogs_count);
Assert.Equal(posts.Count(), posts_count);
}

[Fact]
public void SaveCopyAsyncTest()
{
var posts = GeneratePosts();
var blogs = GenerateBlogs();
_dbContext.Posts.AddRange(posts);
_dbContext.Blogs.AddRange(blogs);

_dbContext.SaveByCopyChanges();

var blogs_count = _dbContext.Blogs.Count();
var posts_count = _dbContext.Posts.Count();

Assert.Equal(blogs.Count(), blogs_count);
Assert.Equal(posts.Count(), posts_count);
}

[Fact]
public async Task SaveCopyGraphAsyncTest()
{
var post = new Post
{
Online = true,
Content = @"Some Content for unit test",
Title = "Post title",
Blog = new Blog
{
Url = "http://blog.com"
}
};

await _dbContext.Posts.AddAsync(post);

await _dbContext.SaveByCopyChangesAsync();

var blogsCount = await _dbContext.Blogs.CountAsync();
var postsCount = await _dbContext.Posts.CountAsync();

Assert.Equal(1, blogsCount);
Assert.Equal(1, postsCount);

var expected = await _dbContext.Blogs
.Where(x => Microsoft.EntityFrameworkCore.EF.Functions.Like(x.Url, "%blog.com%"))
.CountAsync();

Assert.Equal(1, expected);
}

private static IEnumerable<Post> GeneratePosts(string title = "default title", long count = 100)
{
for (var i = 0; i < count; i++)
{
yield return new Post
{
Online = i % 2 == 0,
Content = $"Post some content {Guid.NewGuid().ToString()} into {title}-{i}",
PostDate = DateTime.Now,
Title = $"{title}-{i}",
CreationDateTime = DateTime.Now
};
}
}

private static IEnumerable<Blog> GenerateBlogs(string url = "default url", long count = 100)
{
for (var i = 0; i < count; i++)
{
yield return new Blog
{
Url = $"https://{url}/{i}",
CreationDateTime = DateTime.Now
};
}
}

public void Dispose()
{
_dbContext.Database.ExecuteSqlRaw(@"TRUNCATE TABLE post RESTART IDENTITY CASCADE;
TRUNCATE TABLE blog RESTART IDENTITY CASCADE;");
_dbContext.Dispose();
}
}
}
10 changes: 8 additions & 2 deletions EF.Extensions.PgCopy/DbContextExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public static class DbContextExtensions
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<int> SaveByCopyChangesAsync(this DbContext dbContext,
CancellationToken cancellationToken)
CancellationToken cancellationToken=default)
{
if (!dbContext.ChangeTracker.HasChanges()) return await dbContext.SaveChangesAsync(cancellationToken);

Expand Down Expand Up @@ -134,8 +134,14 @@ private static int SaveByCopyEntity(DbContext dbContext,

var saveAllMethodInfo = copyHelper.GetType()
.GetMethod("SaveAll", BindingFlags.Instance | BindingFlags.Public);

var entities =
castMethod.Invoke(null, new object[] {dbContext.ChangeTracker.Entries().Select(x => x.Entity)});
castMethod.Invoke(null, new object[] {dbContext
.ChangeTracker
.Entries()
.Where(x => x.Entity.GetType() == entityType)
.Select(x => x.Entity)});

return Convert.ToInt32(saveAllMethodInfo?.Invoke(copyHelper,
new[] {(NpgsqlConnection) dbContext.Database.GetDbConnection(), entities}));
}
Expand Down
17 changes: 1 addition & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Based on [PostgreSQLCopyHelper](https://github.com/PostgreSQLCopyHelper/PostgreS
## Installation

```shell
dotnet add package EF.Extensions.PgCopy --version 1.0.0
dotnet add package EF.Extensions.PgCopy --version 1.0.2
```

### Example
Expand Down Expand Up @@ -53,18 +53,3 @@ Intel Core i7-9750H CPU 2.60GHz, 1 CPU, 12 logical and 6 physical cores
| Save | 1000000 | 372,285.08 ms | 47,559.949 ms | 137,221.328 ms | 319,992.52 ms |
| SaveEfCopy | 1000000 | 82,974.09 ms | 2,410.985 ms | 6,878.675 ms | 81,184.00 ms |


## TODO

- [x] Test Multi entities tracking (SaveByCopyChanges)
- [x] mixing saving entities with saveChanges and SaveByCopyChanges functions at the same time
- [x] Auto load from NpgsqlDbType and BuiltInPostgresType attribute
- [x] Get DBConnection from dbContext.Database
- [x] Test with different column types
- [x] BenchMark COPY vs multi insert methods
- [x] Caching PostgreSQLCopyHelperFactory
- [x] SaveCopyChanges extension
- [x] Packaging library
- [x] Github Actions
- [ ] Transaction handling
- [ ] Unit tests && update build
Loading

0 comments on commit 5badc8f

Please sign in to comment.