How should I be configuring spring and hibernate so that my Integration Tests replicate properly the behaviour of the Web application? - nhibernate

We have a web application based on NSpring 1.2 and NHibernate 2 and use HibernateTemplate. The web application is configured to use OpenSessionInViewModule.
In our integration tests however the hibernate session is marked as InitDeferredClose and for the most part this works fine for our tests. There are some service functions that work fine in the context of the web application but fail when called from a test harness.
For example : I have one function that creates and updates a number of objects within a transaction. The function is marked with the Transaction attribute but the test fails with the message :
Illegal attempt to associate a collection with two open sessions
When called from the web application the transaction completes successfully
How should I be configuring spring and hibernate so that my Integration Tests replicate properly the functionnality of the Web application ?

You should create a SessionScope instance in the SetUp part of test and then close (dispose) it at the end (TearDown). This should mimic OSIV model quite well. Here's a simplified sample:
using System;
using NHibernate;
using NUnit.Framework;
using Spring.Data.NHibernate.Support;
[TestFixture]
public class OsivKindOfTest
{
private SessionScope scope;
// get LocalSessionFactoryObject from somewhere
// see Spring.Testing.NUnit and auto-injection
private ISessionFactory sessionFactory;
[SetUp]
public void OnSetUp()
{
scope = new SessionScope(sessionFactory, null, true, FlushMode.Never, true);
}
public void TestSomething()
{
// just a dummy demo
Console.WriteLine(sessionFactory.GetCurrentSession().Statistics.EntityCount);
}
[TearDown]
public void TearDown()
{
if (scope != null)
{
scope.Dispose();
}
}
}
This sample expects that Spring's LocalSessionFactoryObject has ExposeTransactionAwareSessionFactory set to true

I have rewritten my integration test fixtures to inherit from the AbstractTransactionalDbProviderSpringContextTests class provided by the Spring testing framework.
This indeed runs each test in its own transaction with a (by default) rollback at the end of the test. Apart from solving the problem of two open sessions, my tests run a lot quicker (no need to clear the database each time).
An important point to keep in mind when using the spring testing framework is that it is necessary to ensure the spring application context of the application code and that of the test framework are the one and the same otherwise the outer transaction and the inner transaction would be created by two different Hibernate Session Factories

Related

WebApplicationFactory and TestServer in integration tests for ASP.NET Core

I have two integ test classes defined as below. When I run tests in ApiControllerIT, all runs successfully. The same for FoundationControllerIT. However, when I run both together (by running the enclosing folder), tests fail.
The error message is:
Scheduler with name 'DefaultQuartzScheduler' already exists.
I have this definition in my Startup.cs file:
services.AddSingleton (IHostedService, QuartzHostedService);
So obviously this line causes the issue (if I remove this line, all testing together runs OK). So my question is - I'm a newbie from Java.. so I don't have a very good insight into .NET Core Integ test framework, but my understanding is - TestServer is created for each of test classes, e.g. One TestServer for ApiControllerIT, and the other for FoundationControllerIT. Is this incorrect? I'm just frustrated how come I'm getting a message:
Scheduler with name 'DefaultQuartzScheduler' already exists.
when I run two separate test classes?? How come the TestServers interfere each other?
public class ApiControllerIT : IClassFixture<WebApplicationFactory<Startup>>
{
private readonly WebApplicationFactory<Startup> _factory;
public ApiControllerIT(WebApplicationFactory<Startup> factory)
{
_factory = factory;
}
// tests ...
}
public class FoundationControllerIT : IClassFixture<WebApplicationFactory<Startup>>
{
private readonly WebApplicationFactory<Startup> _factory;
public FoundationControllerIT(WebApplicationFactory<Startup> factory)
{
_factory = factory;
}
// tests ...
}
I might a bit late on this but I also had this problem and it might still be useful for others in the future.
The problem comes because the WebApplicationFactory will create two instances of your Startup class. This is drastically different from your normal service start, where you only have one instance of Startup.
(It might be a bit different in your case, but I am using a Singleton instance to create and manage my Schedulers throughout my application.)
The WebApplicationFactory also calls ConfigureServices and Configure on both of them. So even your singletons will be there twice, one for each Startup instance. This is not a problem because the Startup instances will have their own ServiceProvider. It only comes to problems if (multiple) singleton instances access the same static properties of something. In our case, this is the SchedulerBuilder using SchedulerFactory using SchedulerRepository within Quartz, which is a >real< singleton and uses this code:
/// <summary>
/// Gets the singleton instance.
/// </summary>
/// <value>The instance.</value>
public static SchedulerRepository Instance { get; } = new SchedulerRepository();
This means that your independent Singleton classes still use the same SchedulerRepository within Quartz, which explains why you get the exception.
Depending on what you are testing within your tests you have some options to tackle this issue.
The SchedulerRepository has a lookup method, which you could use to check if the Scheduler was already created by another instance: public virtual Task<IScheduler?> Lookup(string schedName, CancellationToken cancellationToken = default) - So you either just take the existing Scheduler or you generate another one with a different name
Catch the exception and do nothing. (this only really makes sense if your tests do not need Quartz, which is probably unlikely but I still wanted to list this option)
I cannot tell you what makes most sense in your case as this is completely dependent on what your application does and what you want to test, but I will probably stick with one variant of option 1.

Project Reactor Schedulers elastic using old threadlocal value

I am using spring webflux to call one service from another via Schedulers.elastic()
Mono<Integer> anaNotificationCountObservable = wrapWithRetryForFlux(wrapWithTimeoutForFlux(
notificationServiceMediatorFlux.getANANotificationCountForUser(userId).subscribeOn(reactor.core.scheduler.Schedulers.elastic())
)).onErrorReturn(0);
In main thread i am setting one InhertitableThreadLocal variable and in the child thread I am trying to access it and it is working fine.
This is my class for storing threadlocal
#Component
public class RequestCorrelation {
public static final String CORRELATION_ID = "correlation-id";
private InheritableThreadLocal<String> id = new InheritableThreadLocal<>();
public String getId() {
return id.get();
}
public void setId(final String correlationId) {
id.set(correlationId);
}
public void removeCorrelationId() {
id.remove();
}
}
Now the issue is first time its working fine meaning the value i am setting in threadlocal is passed to other services.
But second time also, it is using old id(generated in last request).
I tried using Schedulers.newSingle() instead of elastic(), then its working fine.
So think since elastic() is re-using threads, thats why it is not able to clear / or it is re-using.
How should i resolve issue.
I am setting thread local in my filter and clearing the same in myfiler
requestCorrelation.setId(UUID.randomUUID().toString());
chain.doFilter(req,res)
requestCorrelation.removeCorrelationId();
You should never tie resources or information to a particular thread when leveraging a reactor pipeline. Reactor is itself scheduling agnostic; developers using your library can choose to schedule work on another scheduler - if you decide to force a scheduling model you might lose performance benefits.
Instead you can store data inside the reactor context. This is a map-like structure that’s tied to the subscriber and independent of the scheduling arrangement.
This is how projects like spring security and micrometer store information that usually belongs in a threadlocal.

Arquillian persistence extension - #UsingDataset seed once for all tests

I have a JPA based application that is read only from the database, it therefore makes sense only to seed the database once before the tests start. Is it possible to do this using the Arquillian persistence extension? I believe it is trying to reseed/clean for every test?
I have tried the following
#RunWith(Arquillian.class)
#UsingDataset("mydataset.xml")
#Cleanup(phase = TestExecutionPhase.NONE)
public class MyArquillianTest {
//Deployable method and tests
}
I've also set the defaultDataSeedStrategy to REFRESH in the arquillian.xml.

NHibernate Passing Session to the Repository

How would I go about passing a session to a repository class?
Let's say that the I have two projects.
1) TestSuite
2) BusinessObjects
The repository is contained in the BusinessObjects project. The NHibernate session is opened in the TestSuite project. Now, I want to use the same session since the TestSuite project starts a transaction on that session. Currently, I am using the following:
var repository = new CustomerRepository(_session);
Of course, this looks ugly! I am thinking somehow a dependency injection framework can be hooked and provide me with the ISession object without having to pass into the repository.
In our WCF Service we actually use a UnitOfWork which wraps a single operation and stores the ISession for that operation.
The repositories know how to get an ISession from the current unit of work they are running under.
In terms of testing we have a base test class that any test class which contains tests that touch the database inherits from. We then control the starting and ending of a unit of work in the testfixturesetup. Has worked fairly well for us once you get use to the fact that in the version of NUnit we use teardown is NOT guaranteed to run (in case of an unhandled exception during setup or the test).

WCF, SubSonic SimpleRepository and multithreading

I'm currently in the process of writing a WCF REST service with SubSonic SimpleRepository and the WCF REST Contrib library. The service is going to be hosted on IIS 7. The database is going to be MS SQL Server. I could not really find a good example which is using this combination of technologies on the internet. The service should expose a database in a RESTful manner but also contains some business rules (e.g. registering users, saving statistics) so I can't use ADO.net Data Services. Because there are going to be a lot of clients accessing the service at the same time it's important that the service can serve several clients at the same time.
For good performance I want to use the following service behaviour:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession, ConcurrencyMode=ConcurrencyMode.Multiple)]
There are no instance variables in the Service class and as I understand it, those attribute values cause new a instance of the service class to be created for every call (not per session because it is called over https).
I used the following simple class for creating the SimpleRepository once (singleton):
public class DB
{
private static SimpleRepository _Repository;
public static SimpleRepository Repository
{
get
{
if (_Repository == null)
{
_Repository = new SimpleRepository("5Drive", SimpleRepositoryOptions.RunMigrations);
}
return _Repository;
}
}
}
Here is an example method of my service:
Interface:
[OperationContract]
[WebGet(UriTemplate = "vehicles")]
[WebDispatchFormatter]
Vehicles GetVehicles();
Implementation:
public Vehicles GetVehicles()
{
// get all vehicles for the logged in user
var vehicles = from v in DB.Repository.All<Vehicle>()
where v.UserID == GetUserID()
orderby v.Name
select v;
return new Vehicles(vehicles);
}
So, here is my question: can I do it this way? Is SimpleRepository thread-safe? Do I have to create a SimpleRepository in every method instead of using a singleton? What about performance when I do that? I looked at the SimpleRepository source code and I think that the migration code is not thread safe because the "private readonly List migrated;" is not synchronized but I might be wrong.
Maybe I'm missing something and I can just ignore multi-threading and configure IIS differently?
Thanks for your help!