Browse Source

Add database connection unit test using ef

master
yangxiaodong 7 years ago
parent
commit
32e7452d4a
13 changed files with 81 additions and 391 deletions
  1. +3
    -0
      README.md
  2. +45
    -40
      test/DotNetCore.CAP.EntityFrameworkCore.Test/ConnectionUtil.cs
  3. +4
    -3
      test/DotNetCore.CAP.EntityFrameworkCore.Test/DatabaseTestHost.cs
  4. +0
    -27
      test/DotNetCore.CAP.EntityFrameworkCore.Test/DbUtil.cs
  5. +0
    -53
      test/DotNetCore.CAP.EntityFrameworkCore.Test/DefaultPocoTest.cs
  6. +2
    -0
      test/DotNetCore.CAP.EntityFrameworkCore.Test/DotNetCore.CAP.EntityFrameworkCore.Test.csproj
  7. +0
    -12
      test/DotNetCore.CAP.EntityFrameworkCore.Test/EnsuranceTest.cs
  8. +26
    -67
      test/DotNetCore.CAP.EntityFrameworkCore.Test/MessageStoreTest.cs
  9. +1
    -1
      test/DotNetCore.CAP.EntityFrameworkCore.Test/TestHost.cs
  10. +0
    -22
      test/DotNetCore.CAP.EntityFrameworkCore.Test/Utilities/ScratchDatabaseFixture.cs
  11. +0
    -139
      test/DotNetCore.CAP.EntityFrameworkCore.Test/Utilities/SqlServerTestStore.cs
  12. +0
    -20
      test/DotNetCore.CAP.EntityFrameworkCore.Test/Utilities/TestEnvironment.cs
  13. +0
    -7
      test/DotNetCore.CAP.EntityFrameworkCore.Test/config.json

+ 3
- 0
README.md View File

@@ -1,3 +1,6 @@
[![Build status](https://ci.appveyor.com/api/projects/status/4mpe0tbu7n126vyw?svg=true)](https://ci.appveyor.com/project/yuleyule66/cap)
[![Build status](https://ci.appveyor.com/api/projects/status/4mpe0tbu7n126vyw/branch/master?svg=true)](https://ci.appveyor.com/project/yuleyule66/cap/branch/master)

# cap
A .net core middleware of eventually consistent in distributed architectures, now developing...


+ 45
- 40
test/DotNetCore.CAP.EntityFrameworkCore.Test/ConnectionUtil.cs View File

@@ -3,44 +3,49 @@ using System.Data.SqlClient;

namespace DotNetCore.CAP.EntityFrameworkCore.Test
{
public static class ConnectionUtil
{
private const string DatabaseVariable = "Cap_SqlServer_DatabaseName";
private const string ConnectionStringTemplateVariable = "Cap_SqlServer_ConnectionStringTemplate";

private const string MasterDatabaseName = "master";
private const string DefaultDatabaseName = @"DotNetCore.CAP.EntityFrameworkCore.Test";

private const string DefaultConnectionStringTemplate = @"Server=.\sqlexpress;Database={0};Trusted_Connection=True;";

public static string GetDatabaseName()
{
return Environment.GetEnvironmentVariable(DatabaseVariable) ?? DefaultDatabaseName;
}

public static string GetMasterConnectionString()
{
return string.Format(GetConnectionStringTemplate(), MasterDatabaseName);
}

public static string GetConnectionString()
{
return string.Format(GetConnectionStringTemplate(), GetDatabaseName());
}

private static string GetConnectionStringTemplate()
{
return
Environment.GetEnvironmentVariable(ConnectionStringTemplateVariable) ??
DefaultConnectionStringTemplate;
}

public static SqlConnection CreateConnection(string connectionString = null)
{
connectionString = connectionString ?? GetConnectionString();
var connection = new SqlConnection(connectionString);
connection.Open();
return connection;
}
}
public static class ConnectionUtil
{
private const string DatabaseVariable = "Cap_SqlServer_DatabaseName";
private const string ConnectionStringTemplateVariable = "Cap_SqlServer_ConnectionStringTemplate";

private const string MasterDatabaseName = "master";
private const string DefaultDatabaseName = @"DotNetCore.CAP.EntityFrameworkCore.Test";

//private const string DefaultConnectionStringTemplate = @"Server=.\sqlexpress;Database={0};Trusted_Connection=True;";
private const string DefaultConnectionStringTemplate = @"Server=192.168.2.206;Initial Catalog={0};User Id=sa;Password=123123;MultipleActiveResultSets=True";

public static string GetDatabaseName()
{
return Environment.GetEnvironmentVariable(DatabaseVariable) ?? DefaultDatabaseName;
}

public static string GetMasterConnectionString()
{
return string.Format(GetConnectionStringTemplate(), MasterDatabaseName);
}

public static string GetConnectionString()
{
//if (Environment.GetEnvironmentVariable("ASPNETCore_Environment") == "Development")
//{
// return "Server=192.168.2.206;Initial Catalog=Test2;User Id=cmswuliu;Password=h7xY81agBn*Veiu3;MultipleActiveResultSets=True";
//}
return string.Format(GetConnectionStringTemplate(), GetDatabaseName());
}

private static string GetConnectionStringTemplate()
{
return
Environment.GetEnvironmentVariable(ConnectionStringTemplateVariable) ??
DefaultConnectionStringTemplate;
}

public static SqlConnection CreateConnection(string connectionString = null)
{
connectionString = connectionString ?? GetConnectionString();
var connection = new SqlConnection(connectionString);
connection.Open();
return connection;
}
}
}

+ 4
- 3
test/DotNetCore.CAP.EntityFrameworkCore.Test/DatabaseTestHost.cs View File

@@ -1,4 +1,5 @@
using System.Data;
using System.Threading.Tasks;
using Dapper;
using Microsoft.EntityFrameworkCore;

@@ -26,10 +27,10 @@ namespace DotNetCore.CAP.EntityFrameworkCore.Test
{
using (CreateScope())
{
var context = GetService<CapDbContext>();
var context = GetService<TestDbContext>();
context.Database.EnsureDeleted();
context.Database.Migrate();
_sqlObjectInstalled = true;
_sqlObjectInstalled = true;
}
}
}
@@ -38,7 +39,7 @@ namespace DotNetCore.CAP.EntityFrameworkCore.Test
{
using (CreateScope())
{
var context = GetService<CapDbContext>();
var context = GetService<TestDbContext>();

var commands = new[]
{


+ 0
- 27
test/DotNetCore.CAP.EntityFrameworkCore.Test/DbUtil.cs View File

@@ -1,27 +0,0 @@
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;

namespace DotNetCore.CAP.EntityFrameworkCore.Test
{
public static class DbUtil
{
public static IServiceCollection ConfigureDbServices(string connectionString, IServiceCollection services = null) {
return ConfigureDbServices<CapDbContext>(connectionString, services);
}

public static IServiceCollection ConfigureDbServices<TContext>(string connectionString, IServiceCollection services = null) where TContext : DbContext {
if (services == null) {
services = new ServiceCollection();
}
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddDbContext<TContext>(options => options.UseSqlServer(connectionString));
return services;
}

public static TContext Create<TContext>(string connectionString) where TContext : DbContext {
var serviceProvider = ConfigureDbServices<TContext>(connectionString).BuildServiceProvider();
return serviceProvider.GetRequiredService<TContext>();
}
}
}

+ 0
- 53
test/DotNetCore.CAP.EntityFrameworkCore.Test/DefaultPocoTest.cs View File

@@ -1,53 +0,0 @@
using System.Threading.Tasks;
using DotNetCore.CAP.Infrastructure;
using Microsoft.AspNetCore.Builder.Internal;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Xunit;

namespace DotNetCore.CAP.EntityFrameworkCore.Test
{
public class DefaultPocoTest : IClassFixture<ScratchDatabaseFixture>
{
private readonly ApplicationBuilder _builder;

public DefaultPocoTest(ScratchDatabaseFixture fixture)
{
var services = new ServiceCollection();

services
.AddDbContext<CapDbContext>(o => o.UseSqlServer(fixture.ConnectionString))
.AddConsistency()
.AddEntityFrameworkStores<CapDbContext>();

services.AddLogging();

var provider = services.BuildServiceProvider();
_builder = new ApplicationBuilder(provider);

using (var scoped = provider.GetRequiredService<IServiceScopeFactory>().CreateScope())
using (var db = scoped.ServiceProvider.GetRequiredService<CapDbContext>())
{
db.Database.EnsureCreated();
}
}

[Fact]
public async Task EnsureStartupUsageWorks()
{
var messageStore = _builder.ApplicationServices.GetRequiredService<ICapMessageStore>();
var messageManager = _builder.ApplicationServices.GetRequiredService<ICapMessageStore>();

Assert.NotNull(messageStore);
Assert.NotNull(messageManager);

var message = new CapSentMessage();

var operateResult = await messageManager.StoreSentMessageAsync(message);
Assert.True(operateResult.Succeeded);

operateResult = await messageManager.RemoveSentMessageAsync(message);
Assert.True(operateResult.Succeeded);
}
}
}

+ 2
- 0
test/DotNetCore.CAP.EntityFrameworkCore.Test/DotNetCore.CAP.EntityFrameworkCore.Test.csproj View File

@@ -37,10 +37,12 @@
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.2" />
<PackageReference Include="System.Data.SqlClient" Version="4.3.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="1.1.2" />
</ItemGroup>

<ItemGroup>
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.1" />
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>



+ 0
- 12
test/DotNetCore.CAP.EntityFrameworkCore.Test/EnsuranceTest.cs View File

@@ -1,12 +0,0 @@
using Xunit;

namespace DotNetCore.CAP.EntityFrameworkCore.Test
{
public class EnsuranceTest : DatabaseTestHost
{
[Fact]
public void Ensure()
{
}
}
}

+ 26
- 67
test/DotNetCore.CAP.EntityFrameworkCore.Test/MessageStoreTest.cs View File

@@ -1,73 +1,58 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using DotNetCore.CAP.Infrastructure;
using DotNetCore.CAP.Test;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Xunit;

namespace DotNetCore.CAP.EntityFrameworkCore.Test
{
public class MessageStoreTest : MessageManagerTestBase, IClassFixture<ScratchDatabaseFixture>
public class MessageStoreTest : DatabaseTestHost
{
private readonly ScratchDatabaseFixture _fixture;

public MessageStoreTest(ScratchDatabaseFixture fixture)
{
_fixture = fixture;
}

public class ApplicationDbContext : CapDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
}

[Fact]
public void CanCreateSentMessageUsingEF()
{
using (var db = CreateContext())
{
var guid = Guid.NewGuid().ToString();
db.CapSentMessages.Add(new CapSentMessage
var message = new CapSentMessage
{
Id = guid,
Content = "this is message body",
StateName = StateName.Enqueued
});
};
db.Attach(message).State = Microsoft.EntityFrameworkCore.EntityState.Added;

db.SaveChanges();
Assert.True(db.CapSentMessages.Any(u => u.Id == guid));
Assert.NotNull(db.CapSentMessages.FirstOrDefault(u => u.StateName == StateName.Enqueued));
}
}

[Fact]
public async Task CanCreateUsingManager()
{
var manager = CreateManager();
var guid = Guid.NewGuid().ToString();
var message = new CapSentMessage
{
Id = guid,
Content = "this is message body",
StateName = StateName.Enqueued,
};
//[Fact]
//public async Task CanCreateUsingManager()
//{
// var manager = CreateManager();
// var guid = Guid.NewGuid().ToString();
// var message = new CapSentMessage
// {
// Id = guid,
// Content = "this is message body",
// StateName = StateName.Enqueued,
// };

var result = await manager.StoreSentMessageAsync(message);
Assert.NotNull(result);
Assert.True(result.Succeeded);
// var result = await manager.StoreSentMessageAsync(message);
// Assert.NotNull(result);
// Assert.True(result.Succeeded);

result = await manager.RemoveSentMessageAsync(message);
Assert.NotNull(result);
Assert.True(result.Succeeded);
}
// result = await manager.RemoveSentMessageAsync(message);
// Assert.NotNull(result);
// Assert.True(result.Succeeded);
//}

public CapDbContext CreateContext(bool delete = false)
public TestDbContext CreateContext(bool delete = false)
{
var db = DbUtil.Create<CapDbContext>(_fixture.ConnectionString);
var db = Provider.GetRequiredService<TestDbContext>();
if (delete)
{
db.Database.EnsureDeleted();
@@ -75,31 +60,5 @@ namespace DotNetCore.CAP.EntityFrameworkCore.Test
db.Database.EnsureCreated();
return db;
}

protected override object CreateTestContext()
{
return CreateContext();
}

protected override void AddMessageStore(IServiceCollection services, object context = null)
{
services.AddSingleton<ICapMessageStore>(new CapMessageStore<CapDbContext>((CapDbContext)context));
}

protected override CapSentMessage CreateTestSentMessage(string content = "")
{
return new CapSentMessage
{
Content = content
};
}

protected override CapReceivedMessage CreateTestReceivedMessage(string content = "")
{
return new CapReceivedMessage()
{
Content = content
};
}
}
}
}

+ 1
- 1
test/DotNetCore.CAP.EntityFrameworkCore.Test/TestHost.cs View File

@@ -29,7 +29,7 @@ namespace DotNetCore.CAP.EntityFrameworkCore.Test

var connectionString = ConnectionUtil.GetConnectionString();
//services.AddSingleton(new SqlServerOptions { ConnectionString = connectionString });
services.AddDbContext<CapDbContext>(options => options.UseSqlServer(connectionString));
services.AddDbContext<TestDbContext>(options => options.UseSqlServer(connectionString));

_services = services;
}


+ 0
- 22
test/DotNetCore.CAP.EntityFrameworkCore.Test/Utilities/ScratchDatabaseFixture.cs View File

@@ -1,22 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Internal;

namespace DotNetCore.CAP.EntityFrameworkCore.Test
{
public class ScratchDatabaseFixture : IDisposable
{
private LazyRef<SqlServerTestStore> _testStore;

public ScratchDatabaseFixture() {
_testStore = new LazyRef<SqlServerTestStore>(() => SqlServerTestStore.CreateScratch());
}

public string ConnectionString => _testStore.Value.Connection.ConnectionString;

public void Dispose() {
if (_testStore.HasValue) {
_testStore.Value?.Dispose();
}
}
}
}

+ 0
- 139
test/DotNetCore.CAP.EntityFrameworkCore.Test/Utilities/SqlServerTestStore.cs View File

@@ -1,139 +0,0 @@
using System;
using System.Data.Common;
using System.Data.SqlClient;
using System.IO;
using System.Threading;

namespace DotNetCore.CAP.EntityFrameworkCore.Test
{
public class SqlServerTestStore : IDisposable
{
public const int CommandTimeout = 90;

public static string CreateConnectionString(string name) {
var connStrBuilder = new SqlConnectionStringBuilder(TestEnvironment.Config["Test:SqlServer:DefaultConnectionString"]) {
InitialCatalog = name
};

return connStrBuilder.ConnectionString;
}

public static SqlServerTestStore CreateScratch(bool createDatabase = true)
=> new SqlServerTestStore(GetScratchDbName()).CreateTransient(createDatabase);

private SqlConnection _connection;
private readonly string _name;
private bool _deleteDatabase;

private SqlServerTestStore(string name) {
_name = name;
}

private static string GetScratchDbName() {
string name;
do {
name = "Scratch_" + Guid.NewGuid();
} while (DatabaseExists(name)
|| DatabaseFilesExist(name));

return name;
}

private static void WaitForExists(SqlConnection connection) {
var retryCount = 0;
while (true) {
try {
connection.Open();

connection.Close();

return;
}
catch (SqlException e) {
if (++retryCount >= 30
|| (e.Number != 233 && e.Number != -2 && e.Number != 4060)) {
throw;
}

SqlConnection.ClearPool(connection);

Thread.Sleep(100);
}
}
}

private SqlServerTestStore CreateTransient(bool createDatabase) {
_connection = new SqlConnection(CreateConnectionString(_name));

if (createDatabase) {
using (var master = new SqlConnection(CreateConnectionString("master"))) {
master.Open();
using (var command = master.CreateCommand()) {
command.CommandTimeout = CommandTimeout;
command.CommandText = $"{Environment.NewLine}CREATE DATABASE [{_name}]";

command.ExecuteNonQuery();

WaitForExists(_connection);
}
}
_connection.Open();
}

_deleteDatabase = true;
return this;
}

private static bool DatabaseExists(string name) {
using (var master = new SqlConnection(CreateConnectionString("master"))) {
master.Open();

using (var command = master.CreateCommand()) {
command.CommandTimeout = CommandTimeout;
command.CommandText = $@"SELECT COUNT(*) FROM sys.databases WHERE name = N'{name}'";

return (int)command.ExecuteScalar() > 0;
}
}
}

private static bool DatabaseFilesExist(string name) {
var userFolder = Environment.GetEnvironmentVariable("USERPROFILE") ??
Environment.GetEnvironmentVariable("HOME");
return userFolder != null
&& (File.Exists(Path.Combine(userFolder, name + ".mdf"))
|| File.Exists(Path.Combine(userFolder, name + "_log.ldf")));
}

private void DeleteDatabase(string name) {
using (var master = new SqlConnection(CreateConnectionString("master"))) {
master.Open();

using (var command = master.CreateCommand()) {
command.CommandTimeout = CommandTimeout;
// Query will take a few seconds if (and only if) there are active connections

// SET SINGLE_USER will close any open connections that would prevent the drop
command.CommandText
= string.Format(@"IF EXISTS (SELECT * FROM sys.databases WHERE name = N'{0}')
BEGIN
ALTER DATABASE [{0}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE [{0}];
END", name);

command.ExecuteNonQuery();
}
}
}

public DbConnection Connection => _connection;

public void Dispose() {
_connection.Dispose();

if (_deleteDatabase) {
DeleteDatabase(_name);
}
}
}
}

+ 0
- 20
test/DotNetCore.CAP.EntityFrameworkCore.Test/Utilities/TestEnvironment.cs View File

@@ -1,20 +0,0 @@
using System.IO;
using Microsoft.Extensions.Configuration;

namespace DotNetCore.CAP.EntityFrameworkCore.Test
{
public class TestEnvironment
{
public static IConfiguration Config { get; }

static TestEnvironment() {
var configBuilder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("config.json", optional: true)
.AddJsonFile("config.test.json", optional: true)
.AddEnvironmentVariables();

Config = configBuilder.Build();
}
}
}

+ 0
- 7
test/DotNetCore.CAP.EntityFrameworkCore.Test/config.json View File

@@ -1,7 +0,0 @@
{
"Test": {
"SqlServer": {
"DefaultConnectionString": "Server=192.168.2.206;Initial Catalog=Test;User Id=cmswuliu;Password=h7xY81agBn*Veiu3;MultipleActiveResultSets=True"
}
}
}

Loading…
Cancel
Save