I am working with Selenium and MSTest as framework and I would like to extend the TestClass, TestMethod and TestCleanup. Right now the tests are derived from a TestBase class that is defined as follows:
[TestClass]
public class TestBase : IDisposable
{
bool disposed = false;
SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true);
public TestContext TestContext { get; set; }
protected HelperSelenium SeleniumHelper { get; set; }
[TestInitialize]
public void TestInitBase()
{
SeleniumHelper = new HelperSelenium(TestContext);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
handle.Dispose();
SeleniumHelper.GetWebDriver().Quit();
// Free any other managed objects here.
//
}
disposed = true;
}
}
The [TestClass] instantiates TestContext and [TestInitialize] instantiates the HelperSelenium with TestContext as a paremeter (this is necessary to tell Selenium which class it should use depending on a TestContext property.
I've tried with this code without success:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class SeleniumTestClass : TestClassAttribute
{
//Prueba para finalizacion de recursos
bool disposed = false;
/// <summary>
/// Bandera para saber si se ha llamado a dispose e instanciacion de un Selfhandle
/// </summary>
SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true);
public TestContext TestContext { get; set; }
public HelperSelenium SeleniumHelper { get; set; }
#region ConfiguraciĆ³n Test
[TestInitialize]
public void TestInitBase()
{
SeleniumHelper = new HelperSelenium(TestContext);
}
public void Dispose()
{
//SeleniumHelper.GetWebDriver().Quit();
//SeleniumHelper.GetWebDriver().Dispose();
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
handle.Dispose();
SeleniumHelper.GetWebDriver().Quit();
// Free any other managed objects here.
//
}
disposed = true;
}
I would like to extend [TestClass] to [SeleniumTestClass] so if I use [SeleniumTestClass] in a derived class all of this would be done automatically. I've trying to do this because we are using EventFiringWebDriver which will throw an exception even inside a Wait.Until loop. Selenium can throw a exception in 2 ways:
An action has been performed that throws an exception, but the
exception is caught by Wait.Until
An action has been performed
that throws an exception, and the exception is outside a
Wait.Until
So if TestMethod fails, I would be able to take a screenshot while catching the exception. I think TestCleanup cannot be inherited so I am not sure if I would be able to catch the exception in the TestCleanup
I know I could wrap up the TestMethod and the TestCleanup each one in a try-catch but that would be cumbersome to do in each test we have and the test we would be creating in the future.
Any help is appreciated.
Try having the abstract class calling a new OnTest method:
[TestClass]
public abstract class TestBase
{
bool disposed = false;
SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true);
public TestContext TestContext { get; set; }
protected HelperSelenium SeleniumHelper { get; set; }
[TestInitialize]
public void TestInitBase()
{
SeleniumHelper = new HelperSelenium(TestContext);
}
public abstract void OnTest();
[TestMethod()]
public void SeleniumTest()
{
try
{
OnTest();
}
catch(Exception ex){
}
}
}
Related
AutoMapper Version Used : 3.3.10
[TestClass]
public class AppControllerTests
{
private IMappingEngine _mappingEngine = null;
private ConfigurationStore _configurationStore = null;
[TestInitialize]
public void SetUp()
{
_configurationStore = new ConfigurationStore(new TypeMapFactory(), MapperRegistry.Mappers);
_configurationStore.AddProfile(new AutoMapperProfile.AppProfile());
_mappingEngine = new MappingEngine(_configurationStore);
}
[TestMethod]
public void GetAppByAccountID()
{
// Error line
var mappingResult = _mappingEngine.Map<Category>(categoryList).AsQueryable();
}
}
public class AppProfile : Profile
{
protected override void Configure()
{
AutoMapperMappingConfigurations();
}
public void AutoMapperMappingConfigurations()
{
Mapper.CreateMap<DomainModels.Category, Category>().ReverseMap();
}
}
Exception:
An exception of type 'AutoMapper.AutoMapperMappingException'
occurred in AutoMapper.dll but was not handled in user code.
Suspect the
_configurationStore.AddProfile(new OOS.PresentationModelService.AutoMapperProfile.AppProfile());
is not able to create an istance of AppProfile if i write the manual mapping it's working as expected.
_configurationStore.CreateMap<Category, Category>().ReverseMap();
I am building an mvc4 n layer application using the following frameworks
1.nhibernate
2.ninject
3.mvc4/Console(For testing)
The layers are(All are class library projects)
1.Presentation(Calling BLL layer)
2.BLL(Calling my DAO layer)
3.Domain(POCOS)
4.Nhibernate(Implementation of DAO)
5.Core
BLL Layer Coding
public interface IUserService
{
IList<User> GetAllActiveUsers();
User GetUserDetailsByUsername(string usernameOrEmail);
}
public class UserService :IUserService
{
private readonly IUserRepository userRepository;
public UserService(IUserRepository userRepository)
{
this.userRepository = userRepository;
}
public IList<User> GetAllActiveUsers()
{
var activeUserList = from user in userRepository.All()
where user.ACTIVE_STATUS == true
select user;
return activeUserList.ToList<User>();
}
public User GetUserDetailsByUsername(string usernameOrEmail)
{
var registerUser = from user in userRepository.All()
where user.USER_NAME == usernameOrEmail
select user;
return (User)registerUser;
}
}
DAO layer Code
public interface IRepository<TKey, TEntity> where TEntity : class
{
IQueryable<TEntity> All();
TEntity FindBy(Expression<Func<TEntity, bool>> expression);
IQueryable<TEntity> FilterBy(Expression<Func<TEntity, bool>> expression);
TEntity FindBy(TKey id);
bool Add(TEntity entity);
bool Add(IEnumerable<TEntity> items);
bool Update(TEntity entity);
bool Delete(TEntity entity);
bool Delete(IEnumerable<TEntity> entities);
}
public interface IUowDAO:IDisposable
{
void Commit();
void Rollback();
}
public interface IUserRepository:IRepository<long,User>
{
}
DAO.Nhibernate Layer
public class IURMSNhibernateRepository<TKey, T> : IRepository<TKey, T> where T : class
{
private readonly ISession _session;
public IURMSNhibernateRepository(ISession session)
{
_session = session;
}
public bool Add(T entity)
{
_session.Save(entity);
return true;
}
public bool Add(IEnumerable<T> items)
{
foreach (T item in items)
{
_session.Save(item);
}
return true;
}
public bool Update(T entity)
{
_session.SaveOrUpdate(entity);
return true;
}
public bool Delete(T entity)
{
_session.Delete(entity);
return true;
}
public bool Delete(IEnumerable<T> entities)
{
foreach (T entity in entities)
{
_session.Delete(entity);
}
return true;
}
public System.Linq.IQueryable<T> All()
{
return _session.Query<T>();
}
public T FindBy(System.Linq.Expressions.Expression<Func<T, bool>> expression)
{
return FilterBy(expression).SingleOrDefault();
}
public System.Linq.IQueryable<T> FilterBy(System.Linq.Expressions.Expression<Func<T, bool>> expression)
{
return All().Where(expression).AsQueryable();
}
public T FindBy(TKey id)
{
return _session.Get<T>(id);
}
}
public class IURMSUnitOfWork:IUowDAO
{
private readonly ISessionFactory _sessionFactory;
private readonly ITransaction _transaction;
public ISession Session { get; private set; }
public IURMSUnitOfWork(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
Session = _sessionFactory.OpenSession();
Session.FlushMode = FlushMode.Auto;
_transaction = Session.BeginTransaction(IsolationLevel.ReadCommitted);
}
public void Commit()
{
if (!_transaction.IsActive)
{
throw new InvalidOperationException("Oops! We don't have an active transaction");
}
_transaction.Commit();
}
public void Rollback()
{
if (_transaction.IsActive)
{
_transaction.Rollback();
}
}
public void Dispose()
{
if (Session.IsOpen)
{
Session.Close();
}
}
}
public class UserRepository:IURMSNhibernateRepository<long,User>,IUserRepository
{
public UserRepository(ISession session)
: base(session)
{
}
}
CORE Layer
public class BuisnessLogicModule:NinjectModule
{
public override void Load()
{
Bind<IUserService>().To<UserService>();
}
}
public class DataAccessLogicModule:NinjectModule
{
public override void Load()
{
Bind<IUowDAO>().To<IURMSUnitOfWork>().InTransientScope();
Bind(typeof(IRepository<,>)).To(typeof(IURMSNhibernateRepository<,>));
Bind<IUserRepository>().To<UserRepository>();
}
}
Console layerCoding
public interface IConsole
{
IList<User> GetAllUsers();
}
public class ConsoleUser:IConsole
{
private readonly IUserService _userService;
public ConsoleUser(IUserService UserService)
{
this._userService = UserService;
}
public IList<IURMSPOC.DOMAIN.User> GetAllUsers()
{
var user = _userService.GetAllActiveUsers();
return user;
}
}
public class TopModule:NinjectModule
{
public override void Load()
{
Bind<IConsole>().To<ConsoleUser>();
}
}
public class Program
{
static void Main(string[] args)
{
IKernel kernel = new StandardKernel(new TopModule());
var modules = new List<INinjectModule>
{
new IURMSPOC.CORE.Dependency.BuisnessLogicModule(),
new IURMSPOC.CORE.Dependency.DataAccessLogicModule(),
};
kernel.Load(modules);
var topClass = kernel.Get<IConsole>();
var message = topClass.GetAllUsers();
System.Console.WriteLine(message);
System.Console.WriteLine("Press enter to continue...");
System.Console.ReadLine();
}
}
But when i am running the application the error shows Error activating ISession
No matching bindings are available, and the type is not self-bindable.
I am new to ninject and nhibernate .Please give me the solution .I understand the problem but can not find any solution.
That's not an issue of Nhibernate, I guess the error comes from the ctor of
public UserRepository(ISession session)
: base(session)
{
}
Where you require an ISession.
You construct the session in IURMSUnitOfWork so there is no way for the UserRepository to determine the session or for the injection to figure out where ISession is coming from...
Instead I'd suggest to refactor your code and inject your unit of work instance to where it is needed, or refactor the repository to care about unit of work.
Easiest would be to extend IUowDAO with something like GetSession()
and change
public UserRepository(IUowDAO dao)
: base(dao.GetSession())
{
}
or something like that...
Your implementation is a little bit strange. Your data access object has the signature of a transaction etc... maybe read this article for a basic unit of work implementation with nhibernate.
What your are missing is basically the session factory.
I want to have my own AppContext in my ApiController (MVC4).
Should be something like
public class TestController : BaseApiController
{
[HttpGet]
public IEnumerable<TestVM> GetAll()
{
// the test service is injected with SimpleInjector
return _testService.GetAll(**base.AppContext**);
}
}
but the ApiController haven't access to the Session.
Are there any solutions to "activate" the Session for specific keys (because I don't want the whole Session)?
Or do you have any other idea (cache or cookie)?
This is the BaseApiController
public abstract class BaseApiController: ApiController
{
public IAppContext AppContext
{
get { return SessionState.AppContext; }
}
}
and this is my IAppContext (it will have more properties in the future)
public interface IAppContext
{
IIdentity User { get; }
/// <summary> Gets the user id. </summary>
/// <value>The user id.</value>
int IdUser { get; }
}
here the application module which is registered in the web.config
public class ApplicationModule : IHttpModule
{
// ...
SessionState.AppContext = _appContext.InitializeNew(
HttpRuntime.AppDomainAppPath, languages);
// ...
}
SessionState class to get the AppContext
public class SessionState : BaseSessionVariables
{
public static IAppContext AppContext
{
get { return SessionState.Get<IAppContext>("AppContext"); }
set { SessionState.Set("AppContext", value); }
}
}
here the BaseSessionVariables class
public static HttpSessionState GetSession()
{
return HttpContext.Current.Session;
}
protected static T Get<T>(string key) where T : class
{
var session = BaseSessionVariables.GetSession();
if (session == null)
{
throw new Exception("No session");
}
return (session[key] as T);
}
Thanks for your help!
Take a look at the implementation below. It should get you headed in the right direction.
Updated IAppContext - Added Setters
public interface IAppContext
{
IIdentity User { get; set; }
/// <summary> Gets the user id. </summary>
/// <value>The user id.</value>
int IdUser { get; set; }
}
Updated Base Controller - Instantiates a new AppContextImplemenation in the OnActionExecuting method
public abstract class BaseApiController: ApiController
{
public IAppContext AppContext {get; set;}
protected override void OnActionExecuting(
ActionExecutingContext filterContext)
{
AppContext = new AppContextImplementation();
}
}
New Class - implements IAppContext and wraps the HttpContext Session. For testing you can then create an TestAppContextImplementation that doesn't rely on Session but some other in memory storage mechanism.
public class AppContextImplementation : IAppContext
{
public IIdentity User
{
get { return HttpContext.Current.Session["User"] as IIdentity; }
set { HttpContext.Current.Session["User"] = value; }
}
int IdUser
{
get { return Convert.ToInt32(Session["IdUser"]); }
set { Session["IdUser"] = value; }
}
}
For ApiControllers, build yourself a DelegatingHandler and push all of your goodies onto request.Properties. You can then retrieve them from your request whether you are testing or running live. The benefit is that you then have zero dependency on Session in your Controller.
MessageHandler
public class ContextHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
// get the goodies to add onto the request
var goodies = /* call to goodieGoodieYumYum */
// add our goodies onto the request
request.Properties.Add(Constants.RequestKey_Goodies, goodies);
// pass along to the next handler
return base.SendAsync(request, cancellationToken);
}
}
Controller Action
var goodies = (List<Goodie>)Request.Properties[Constants.RequestKey_Goodies];
I'm quite new to nhibernate, I was doing all right until I face this problem, It looks like a NHibernate bug, but being a newbie with it, it can certainly be my fault
Having this base class to do all the Id and equality stuff
public abstract class ObjetoConId
{
public ObjetoConId()
{
Id=NewId();
}
public virtual Guid Id {get;private set;}
public override bool Equals(object o)
{
if (Object.ReferenceEquals(this,o))
return true;
if (o==null) return false;
ObjetoConId oId;
oId= o as ObjetoConId;
if (!Object.ReferenceEquals(oId,null))
return (Id.Equals(oId.Id));
return (base.Equals(o));
}
public override int GetHashCode()
{
byte[] bId;
bId=Id.ToByteArray();
return ((Int32)(bId[8]^bId[12])<<24) +
((Int32)(bId[9]^bId[13])<<16) +
((Int32)(bId[10]^bId[14])<<8) +
((Int32)(bId[11]^bId[15]));
}
public virtual bool Equals(ObjetoConId o)
{
if (Object.ReferenceEquals(this,o))
return true;
if (Object.ReferenceEquals(o,null)) return false;
return (Id.Equals(o.Id));
}
public virtual string toString()
{
return this.GetType().FullName
+ "[id=" + Id + "]";
}
protected virtual Guid NewId()
{
return GuidComb.NewGuid();
}
public static bool operator == (ObjetoConId x,ObjetoConId y)
{
if(Object.ReferenceEquals(x,y))
return true;
if(Object.ReferenceEquals(x,null))
return false;
return x.Equals(y);
}
public static bool operator != (ObjetoConId x,ObjetoConId y)
{
return !(x==y);
}
/// <summary>
/// Metodo interno para permitir el testing
/// </summary>
/// <param name="id"></param>
internal void setId(Guid id)
{
Id=id;
}
}
and this entity
public class Propiedad : ObjetoConId,IPropiedad
{
[Obsolete("Persistance Constructor only")]
public Propiedad ()
{
}
public Propiedad (IList<IDescripcionCalificada> descripciones)
{
Descripciones=new Dictionary<string,IDescripcionCalificada>(descripciones.Count);
foreach(IDescripcionCalificada d in descripciones)
Descripciones.Add(d.Nombre,d);
}
#region IPropiedad implementation
public virtual IDictionary<string, IDescripcionCalificada> Descripciones {get;private set;}
#endregion
}
and this mapping
public class MapeoPropiedad : ClassMap<Propiedad>
{
public MapeoPropiedad()
{
Id(x => x.Id).Column("pro_id").GeneratedBy.Assigned();
HasMany<DescripcionCalificada>(x => x.Descripciones)
.Cascade.SaveUpdate()
.AsMap<string>(index => index.Nombre)
;
}
}
The test for it is
[TestFixture]
public class TestPropiedadPersistencia
{
[TestFixtureSetUp]
public void TestFixtureSetUp()
{
string connectionString="Server=127.0.0.1;Database=Ana;User ID=dev-test;Password=dev-test;";
fcfg=Fluently.Configure()
.Database(PostgreSQLConfiguration.PostgreSQL82.ConnectionString(connectionString))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<MapeoPropiedad>());
fcfg.ExposeConfiguration(cfg => new SchemaExport(cfg).Create(false, true));
sessions=fcfg.BuildSessionFactory();
}
ISessionFactory sessions;
FluentConfiguration fcfg;
[TestFixtureTearDown]
public void TestFixtureTearDown()
{
fcfg.ExposeConfiguration(cfg => new SchemaExport(cfg).Drop(false, true));
sessions.Close();
sessions = null;
fcfg = null;
}
[Test]
public void CanCorrectlyMapPropiedad()
{
DescripcionCalificada descri1=new DescripcionCalificada("descri",new Descripcion("Esta es la descri"));
DescripcionCalificada descri2=new DescripcionCalificada("descriLarga",new Descripcion("Esta es la descriLarga"));
Dictionary<string,IDescripcionCalificada> descris=new Dictionary<string, IDescripcionCalificada>(2);
descris.Add(descri1.Nombre,descri1);
descris.Add(descri2.Nombre,descri2);
new PersistenceSpecification<Propiedad>(sessions.OpenSession(),new CustomEqualityComparer() )
.CheckProperty(c => c.Descripciones,descris)
.VerifyTheMappings();
}
}
The thing is that the test fails unless I put Not.LazyLoad() in the mapping
It gives a mapping error
Ana.Nucleo.Lenguaje.Test.TestDescripcionCalificadaPersistencia (TestFixtureSetUp):
FluentNHibernate.Cfg.FluentConfigurationException : An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.
----> NHibernate.InvalidProxyTypeException : The following types may not be used as proxies:
Ana.Catalogacion.Implementacion.Propiedad: method setId should be 'public/protected virtual' or 'protected internal virtual'
without lazy loading it pass, and if I put the Id property in the Propiedad class and not inherit from ObjetoConID it also pass, with and without the Not.LazyLoad().
Anyone can confirm this is a NH bug, or any help will be appreciated
EDIT:
I've found the problem, my fault. I missed the setId internal function not being virtual protected and confused with the setter of the Id property, and thus missunderstood the execption
Fer
I've found the problem, my fault. I missed the setId internal function not being virtual protected and confused with the setter of the Id property, and thus missunderstood the execption
Andreas Ohlund has an excellent article here on how to use Structuremap to wire the NHibernate session so that it enlists in the NSB transaction automatically.
Does anyone know if it is possible to achieve the same with Autofac?
I have been given the awnser by a colleague
public class NHibernateMessageModule : IMessageModule
{
/// <summary>
/// Injected SessionManager.
/// </summary>
public ISessionManager SessionManager { get; set; }
public void HandleBeginMessage()
{
//this session need for NServiceBus and for us
ThreadStaticSessionContext.Bind(SessionManager.OpenSession()); //CurrentSessionContext or ThreadStaticSessionContext
}
public void HandleEndMessage()
{
SessionManager.Session.Flush();
}
public void HandleError()
{
}
}
public interface ISessionManager
{
ISession Session { get; }
ISession OpenSession();
bool IsSessionOpened { get; }
void CloseSession();
}
public class NHibernateSessionManager : ISessionManager
{
private ISessionFactory _sessionFactory;
private ISession _session;
public ISession Session
{
get { return _session; }
private set { _session = value; }
}
public SchemaExport SchemaExport { get; set; }
public NHibernateSessionManager(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
}
public bool IsSessionOpened
{
get { return Session != null && Session.IsOpen; }
}
public ISession OpenSession()
{
if(Session == null)
{
Session = _sessionFactory.OpenSession();
if (SchemaExport != null)
SchemaExport.Execute(true, true, false, Session.Connection, null);
}
return Session;
}
public void CloseSession()
{
if (Session != null && Session.IsOpen)
{
Session.Flush();
Session.Close();
}
Session = null;
}
}
You do exactly the same as in the articke you mention but select one of the Autofac lifescopes. If you have other classes involved in message handling where you want your session to be injected, you use InstancePerLifetimeScope like this
public class EndpointConfig : IConfigureThisEndpoint, AsA_Publisher, IWantCustomInitialization
{
public void Init()
{
var builder = new ContainerBuilder();
builder.Register(s => SessionFactory.CreateSessionFactory()).As<ISessionFactory>().SingleInstance();
builder.Register(x => x.Resolve<ISessionFactory>().OpenSession()).As<ISession>().InstancePerLifetimeScope();
var container = builder.Build();
Configure.With().AutofacBuilder(container);
}
}
You can also register any other dependencies you need within your NSB context and you will be sure it is instantiated and dosposed properly due to the use of child container.