Answer the question
In order to leave comments, you need to log in
Answer the question
In order to leave comments, you need to log in
Good afternoon!
So far I've found a working version that is being tested very well.
1. Create several projects:
- DAL.Abstract - interfaces of Generic-repository, specialized repositories and UnitOfWork'a;
- DAL.Real - contains implementations of interfaces from DAL.Abstract;
- DAL.Fakes - fake implementations for unit tests;
- BL.Abstract - business service interfaces;
- BL.Real - here implementations of business service interfaces;
- BL.Fakes - fake implementations of auxiliary services (EmailService, SmsService from Identity);
- BL.Tests - business logic unit tests;
- Core.Models - domain models (code-first).
2. Because Since I use the UnitOfWork template, I had to abandon the ready-made implementation from the Identity.EntityFramework library due to the fact that it contains ready-made classes User, Role, Claims, etc., and I have to drag this library into all projects where you need to use at least User. And after it, the EntityFramework library is dragged into all projects ... I don’t like it, because, in my opinion, the MVC layer should not know about implementation particulars (that is, about EntityFramework).
Therefore, the easiest option is to make a bicycle ... um, your own implementation of all sorts of IUserStore, IPasswordStore and other interfaces from Microsoft.AspNet.Identity.Core (well, and accordingly, create your own User, Role, UserRole, Claims, ExternalLogin classes), which could work with UnitOfWork'om necessary to me.
3. Writing a test:
[TestFixture]
public class UserServiceTests
{
private FakeEmailService _emaiService;
private FakeSmsService _smsService;
private IUserServiceFactory _userServiceFactory;
private IUserService _userSrv;
private IAuthenticationManager _authManager;
private IUserRepository _userRepository;
[SetUp]
public void PreInit()
{
var authManagerMock = new Mock<IAuthenticationManager>();
_authManager = authManagerMock.Object;
_userRepository = new FakeUserRepository();
_smsService = new FakeSmsService();
_emaiService = new FakeEmailService();
_userServiceFactory = new UserServiceFactory(
new FakeUnitOfWorkFactory(_userRepository),
_emaiService, _smsService, _authManager);
_userSrv = _userServiceFactory.Create();
// Заполняем хранилище пользователем "[email protected]"
RegisterExistUser();
}
private RegisterResult RegisterExistUser()
{
var model = new RegisterNewUserViewModel(ConstForTest.Users.ExistUser.Email, ConstForTest.Users.ExistUser.Password);
return RegisterUser(model);
}
// Регистрация пользователя "[email protected]"
private RegisterResult RegisterValidUser()
{
var model = new RegisterNewUserViewModel(ConstForTest.Users.ValidUser.Email, ConstForTest.Users.ValidUser.Password);
return RegisterUser(model);
}
[Category(ConstForTest.Categories.UserServiceTests.RegisterNewUser)]
[Test]
public void RegisterNewUser_ValidEmailAndPassword_AfterRegistrationEmailDoesNotConfirmed()
{
var email = ConstForTest.Users.ValidUser.Email;
// Act
RegisterValidUser();
var foundUser = _userSrv.GetUser(email);
Assert.IsNotNull(foundUser);
Assert.IsFalse(foundUser.EmailConfirmed);
}
}
public class UserService : IUserService
{
private readonly IUnitOfWorkFactory _unitFactory;
private readonly IUserIdentityManagerFactory _userManagerFactory;
private readonly ISignInManagerFactory _signInManagerFactory;
public UserService(IUnitOfWorkFactory unitFactory,
IUserIdentityManagerFactory userManagerFactory,
ISignInManagerFactory signInManagerFactory)
{
_unitFactory = unitFactory;
_userManagerFactory = userManagerFactory;
_signInManagerFactory = signInManagerFactory;
}
public RegisterResult RegisterNewUser(RegisterNewUserViewModel model)
{
using (var unit = _unitFactory.Create())
{
RegisterResult result = new RegisterResult();
IdentityResult identityResult;
try
{
var username = model.Email;
var manager = CreateUserManager(unit.UserRepository);
identityResult = manager.Create(new User(username), model.Password);
if (identityResult.Succeeded)
{
var createdUser = unit.UserRepository.GetByUsernameQuery(username);
manager.AddToRole(createdUser.Id, Roles.Client.ToString());
var confirmEmailCode = manager.GenerateEmailConfirmationToken(createdUser.Id);
result.ConfirmEmailCode = confirmEmailCode;
manager.SendEmail(createdUser.Id, Const.EmailSubjects.Account.ConfirmEmail,
"<Тут содержимое письма для подтверждения е-майл пользователя>");
}
unit.Commit();
}
catch (Exception ex)
{
identityResult = IdentityResult.Failed("В процессе регистрации возникла ошибка. Попробуйте выполнить операцию еще раз.");
unit.Rollback();
}
result.IdentityResult = identityResult;
return result;
}
}
// ... другие методы бизнес-сервиса
}
private UserManager<User, Guid> CreateUserManager(IUserRepository userRepository)
{
return _userManagerFactory.Create(userRepository);
}
public interface IUnitOfWorkFactory
{
IUnitOfWork Create();
IUnitOfWork Create(IsolationLevel level);
}
public class EfUnitOfWorkFactory : IUnitOfWorkFactory
{
public IUnitOfWork Create()
{
return Create(IsolationLevel.ReadCommitted);
}
public IUnitOfWork Create(IsolationLevel level)
{
var uow = new EfUnitOfWork(level);
return uow;
}
}
public interface IUnitOfWork : IDisposable, IUnitOfWorkRepositories
{
void SaveChanges();
void Commit();
void Rollback();
}
public interface IUnitOfWorkRepositories
{
IUserRepository UserRepository { get; }
}
public class EfUnitOfWork : IUnitOfWork
{
private bool _isDisposed = false;
private DbContext _db;
private DbContextTransaction _transaction;
public EfUnitOfWork(IsolationLevel level = IsolationLevel.ReadCommitted)
{
_db = new MyApplicationDbContext();
_transaction = _db.Database.BeginTransaction(level);
}
#region IDisposable
protected virtual void Dispose(bool disposing)
{
if (!_isDisposed)
{
if (disposing)
{
if (_transaction != null)
{
_transaction.Rollback();
_transaction.Dispose();
_transaction = null;
}
_db.Dispose();
_db = null;
}
}
_isDisposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
#region IUnitOfWork
public void SaveChanges()
{
_db.SaveChanges();
}
public void Commit()
{
SaveChanges();
_transaction.Commit();
}
public void Rollback()
{
_transaction.Rollback();
}
#endregion
private IUserRepository _userRepo;
public IUserRepository UserRepository
{
get { return _userRepo ?? (_userRepo = new EfUserRepository(_db)); }
}
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question