Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ TestResults
TestResult.xml
/packages/
/publish/
_ReSharper*
8 changes: 5 additions & 3 deletions BuildRevisionCounter.Tests/BuildRevisionCounter.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
<IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType>
<TargetFrameworkProfile />
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
Expand Down Expand Up @@ -90,12 +92,12 @@
</Choose>
<ItemGroup>
<Compile Include="Controllers\CounterControllerTest.cs" />
<Compile Include="DBUtil.cs" />
<Compile Include="IntegrationTest\IntegrationTest.cs" />
<Compile Include="BuildRevisionCounterTest.cs" />
<Compile Include="MongoDBStorageFactory.cs" />
<Compile Include="MongoDBStorageTest.cs" />
<Compile Include="DBStorageFactory.cs" />
<Compile Include="DBStorageTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="MongoDBStorageUtils.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BuildRevisionCounter\BuildRevisionCounter.csproj">
Expand Down
2 changes: 1 addition & 1 deletion BuildRevisionCounter.Tests/BuildRevisionCounterTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class BuildRevisionCounterTest : IntegrationTest
[Test]
public async Task GetAllRevisions()
{
var apiUri = "api/counter";
const string apiUri = "api/counter";

var body = await SendGetRequest(apiUri);
dynamic result = JArray.Parse(body);
Expand Down
12 changes: 9 additions & 3 deletions BuildRevisionCounter.Tests/Controllers/CounterControllerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Threading.Tasks;
using System.Web.Http;
using BuildRevisionCounter.Controllers;
using BuildRevisionCounter.Data;
using NUnit.Framework;

namespace BuildRevisionCounter.Tests.Controllers
Expand All @@ -14,9 +15,8 @@ public class CounterControllerTest
[TestFixtureSetUp]
public void SetUp()
{
MongoDBStorageUtils.SetUpAsync().Wait();

_controller = new CounterController(MongoDBStorageFactory.DefaultInstance);
DBStorageFactory.DefaultInstance.SetUp().Wait();
_controller = new CounterController(DBStorageUtil.GetRevisionStorage(connectionString: DBStorageFactory.DefaultInstance.ConnectionString));
}

[Test]
Expand Down Expand Up @@ -55,5 +55,11 @@ public async Task CurrentReturnsSameValueAsPreviousBumping()
var rev2 = await _controller.Current("CurrentReturnSameValueAsPreviousBumping");
Assert.AreEqual(rev1, rev2);
}

[TestFixtureTearDown]
public void DropDatabaseAsync()
{
DBStorageFactory.DefaultInstance.DropDatabaseAsync().Wait();
}
}
}
40 changes: 40 additions & 0 deletions BuildRevisionCounter.Tests/DBStorageFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using System.Configuration;
using BuildRevisionCounter.Data;
using BuildRevisionCounter.Interfaces;

namespace BuildRevisionCounter.Tests
{
public static class DBStorageFactory
{
private static readonly Lazy<IUserDatabaseTestProvider> _defaultInstance =
new Lazy<IUserDatabaseTestProvider>(() => FromConfigurationConnectionString());

public static IUserDatabaseTestProvider DefaultInstance { get { return _defaultInstance.Value; } }


public static IUserDatabaseTestProvider GetInstance<T>(string connectionStringName = "MongoDBStorage") where T : IUserDatabaseTestProvider
{
return GetDatabaseTestProvider<T>(connectionStringName);
}

public static IUserDatabaseTestProvider FromConfigurationConnectionString(string connectionStringName = "MongoDBStorage")
{
return GetDatabaseTestProvider(connectionStringName);
}

private static IUserDatabaseTestProvider GetDatabaseTestProvider(string connectionStringName)
{
var connectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;
connectionString = DBUtil.SetDatabaseNameRandom(typeof(MongoDBUserStorage), connectionString);
return new MongoDBUserStorage(connectionString);
}

private static IUserDatabaseTestProvider GetDatabaseTestProvider<T>(string connectionStringName) where T : IUserDatabaseTestProvider
{
var connectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;
connectionString = DBUtil.SetDatabaseNameRandom(typeof (T), connectionString);
return (IUserDatabaseTestProvider)Activator.CreateInstance(typeof(T), connectionString);
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Все таки, избавимся от вызовов Activator.
Генерить случайное имя БД, не следует.
В случае сбоя тестов, будут накапливаться БД, которые надо будет удалять в ручную.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

добавлю абстрактный класс, чтобы получить требуемый конструктор.
Как раз ситуация с вопросом на собеседовании (и мой ответ про конструктор): интерфейсом тут конструктор не знаю как прикрутить.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Здесь ничего не надо абстрагироватью Просто new MongoDBUserStorage(connectionString); достаточно.

}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
using System.Threading.Tasks;
using MongoDB.Driver;
using BuildRevisionCounter.Data;
using BuildRevisionCounter.Interfaces;
using NUnit.Framework;

namespace BuildRevisionCounter.Tests
{
[TestFixture]
public class MongoDBStorageTest
public class DBStorageTest
{
private MongoDBStorage _storage;
private IUserDatabaseTestProvider _storage;

[TestFixtureSetUp]
public void SetUp()
Expand All @@ -17,19 +18,17 @@ public void SetUp()

public async Task SetUpAsync()
{
_storage = MongoDBStorageFactory.DefaultInstance;

await _storage.Revisions.Database.Client.DropDatabaseAsync(
_storage.Revisions.Database.DatabaseNamespace.DatabaseName);

_storage = DBStorageFactory.GetInstance<MongoDBUserStorage>();
await _storage.SetUp();
}

[Test]
public async Task EnsureAdminUserCreated()
{
var user = await _storage.FindUser(MongoDBStorage.AdminName);
Assert.AreEqual(MongoDBStorage.AdminName, user.Name);
var adminName = _storage.GetAdminName();
var user = await _storage.FindUser(adminName);
Assert.IsNotNull(user);
Assert.AreEqual(adminName, user.Name);
}

[Test]
Expand Down Expand Up @@ -63,23 +62,24 @@ public async Task EnsureAdminUserMayBeInvokedMultipleTimes()
[Test]
public async Task CreateUserMustThrowExceptionIfUserExists()
{
await _storage.CreateUser(
"CreateUserMustThrowExceptionIfUserExists",
"CreateUserMustThrowExceptionIfUserExists",
new[] {"testRole"});

const string userName = "CreateUserMustThrowExceptionIfUserExists";
const string userPass = "CreateUserMustThrowExceptionIfUserExists";
var userRole = new[] {"testRole"};
await _storage.CreateUser(userName, userPass, userRole);
try
{
await _storage.CreateUser(
"CreateUserMustThrowExceptionIfUserExists",
"CreateUserMustThrowExceptionIfUserExists",
new[] {"testRole"});
await _storage.CreateUser(userName, userPass, userRole);
Assert.Fail();
}
catch (MongoWriteException ex)
catch (DuplicateKeyException)
{
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

в NUnit есть более удобная конструкция ожидания исключения определенного типа.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

так было изначально:

catch (MongoWriteException ex)
{
    Assert.AreEqual(ServerErrorCategory.DuplicateKey, ex.WriteError.Category);
}

а так написано в требованиях:

Codestyle священен. Код в проекте может крив, но код в запросе обязан ему соответсвовать.
;-)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

в NUnit можно пользоваться ExpectedExceptionAttribute или Asserts.Throws для более наглядного и простого способа декларации желаемого поведения.

Я не понял ваш ответ.

Assert.AreEqual(ServerErrorCategory.DuplicateKey, ex.WriteError.Category);
}
}

[TestFixtureTearDown]
public void DropDatabaseAsync()
{
_storage.DropDatabaseAsync().Wait();
}
}
}
62 changes: 62 additions & 0 deletions BuildRevisionCounter.Tests/DBUtil.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System;
using System.Threading.Tasks;
using BuildRevisionCounter.Data;
using BuildRevisionCounter.Interfaces;
using MongoDB.Driver;

namespace BuildRevisionCounter.Tests
{
internal static class DBUtil
{
internal static Task DropDatabaseAsync(this IUserDatabaseTestProvider dataProvider)
{
switch (GetDatabaseKind(dataProvider.GetType()))
{
case DatabaseKind.MongoDB:
return MangoDBDropDatabaseAsync(dataProvider.ConnectionString);
default:
throw new NotImplementedException();
}
}

internal static string SetDatabaseNameRandom(Type storageType, string connectionString)
{
switch (GetDatabaseKind(storageType))
{
case DatabaseKind.MongoDB:
return MangoDBSetDatabaseNameRandom(connectionString);
default:
throw new NotImplementedException();
}
}

private static string MangoDBSetDatabaseNameRandom(string connectionString)
{
var urlBuilder = new MongoUrlBuilder(connectionString)
{
DatabaseName = "brCounterTest_" + Guid.NewGuid().ToString("N")
};
return urlBuilder.ToString();
}

private static Task MangoDBDropDatabaseAsync(string connectionString)
{
var mongoUrl = MongoUrl.Create(connectionString);
return new MongoClient(mongoUrl).DropDatabaseAsync(mongoUrl.DatabaseName);
}


private enum DatabaseKind
{
Unknow,
MongoDB
}

private static DatabaseKind GetDatabaseKind(Type storageType)
{
if (storageType == typeof(MongoDBUserStorage))
return DatabaseKind.MongoDB;
return DatabaseKind.Unknow;
}
}
}
27 changes: 23 additions & 4 deletions BuildRevisionCounter.Tests/IntegrationTest/IntegrationTest.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using BuildRevisionCounter.Data;
using Microsoft.Owin.Hosting;
using NUnit.Framework;

Expand All @@ -23,18 +26,28 @@ public abstract class IntegrationTest
[TestFixtureSetUp]
public void Setup()
{
ChangeConnectionStringInConfigurationManager("MongoDBStorage", DBStorageFactory.DefaultInstance.ConnectionString);

var port = GetFreeTcpPort();
_uri = string.Format("http://localhost:{0}", port);
_application = WebApp.Start<Startup>(_uri);

MongoDBStorageUtils.SetUpAsync().Wait();
DBStorageFactory.DefaultInstance.SetUp().Wait();
}

private static void ChangeConnectionStringInConfigurationManager(string connectionStringName, string connectionString)
{
var settings = ConfigurationManager.ConnectionStrings[connectionStringName];
var fi = typeof (ConfigurationElement).GetField("_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
fi.SetValue(settings, false);
settings.ConnectionString = connectionString;
}

[TestFixtureTearDown]
public void TearDown()
{
_application.Dispose();
DBStorageFactory.DefaultInstance.DropDatabaseAsync().Wait();
}

private static int GetFreeTcpPort()
Expand Down Expand Up @@ -72,14 +85,20 @@ protected async Task<string> SendPostRequest(string apiUri, string userName = "a
string.Format("{0}:{1}", userName, password))));

var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("", "")
});
{
new KeyValuePair<string, string>("", "")
});

var responseMessage = await HttpClient.PostAsync(apiUri, content);
return await responseMessage.Content.ReadAsStringAsync();
}
}

[TestFixtureTearDown]
public void DropDatabaseAsync()
{
DBStorageFactory.DefaultInstance.DropDatabaseAsync().Wait();
}
}

}
27 changes: 0 additions & 27 deletions BuildRevisionCounter.Tests/MongoDBStorageFactory.cs

This file was deleted.

17 changes: 0 additions & 17 deletions BuildRevisionCounter.Tests/MongoDBStorageUtils.cs

This file was deleted.

Loading