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).
Related
We have migrated from a windows Framework 4.7 application to .NET 6.0. Lamar is added for Dependency Injection. We are trying to finalize a refactor to the latest "one-file" program.cs but are getting unexpected System.ObjectDisposedException: 'Cannot access a disposed object'. In all cases, the error is against a Func<T> during object creation.
All our tests are running correctly using the same environment, except to start the tests we (a) create the DI container and (b) use the container to create an object that loads the singletons (from MongoDB):
Container = new Container(registry);
var start = Container.GetInstance<HomeService>();
In the program.cs, we configure the container, but do not get to see it created, or access it inside program.cs. Instead we create HomeService from IServiceProvider during the first use of a controller. Here we were trying to limit the lifecyle scope during creation:
using (var scope = _container.CreateScope())
{
scope.ServiceProvider.GetService<INewHomeService>();
}
For test, we use the same loading steps, except for adding controllers/mvc, of course (i.e. NOT using builder.Services.AddControllers(); and builder.Services.AddMvc() for (integration) testing).
We have tried a lot of different things, like creating our object independently to the startup, but that did not align the singletons. We can get functionality by using static instead, but then we lose dynamic change access.
Some great tips like Resolving instances with ASP.NET Core DI from within ConfigureServices and https://andrewlock.net/exploring-dotnet-6-part-10-new-dependency-injection-features-in-dotnet-6/ but I can't see the specific example to get the live container just after initial creation.
Is it possible that the issue is just the difference between the lifecycle management of the new .NET DI implementation? As this is configuration at the composition root, if we can configure as per our testing approach, it should solve our problem. Other solutions welcome!
The problem 'Cannot access a disposed object' was being caused by a lifecycle mismatch between retained context and the controller access. The code retained a handle on the state object, that had a handle on the factory using FUNC. As we did not configure the Func as anything, it was transient during the controller graph creation, and so was disposed when the controller request ended.
To solve, we tried registering ALL of the FUNC, per How to use Func<T> in built-in dependency injection which was a large task as we had a few factories throughout an old codebase.
The better solution was to create a factory in the composition root, and use an injected IserviceProvider (or with Lamar an IContainer). This is a simple workaround.
With our creation concern, the creation of our object after the completion of the startup process is working correctly as a lazy validation of the first controller access.
I have started using Specflow 3.0 for .NET core tests project with built-in MSTest runner.
I encountered problem while trying to setup one-time method execution in order to persist bearer token value for all running tests in Specflow.
So my idea was to create [BeforeTestRun] Hook static method which would make HTTP request with given credentials. The problem is that those credentials are stored in .runsettings file, so I need to have MSTest's TestContext object in order to access dictionary property.
In Scenario's I'm injecting TestContext and it works fine, however I do not know how to access this object in static [BeforeTestRun] method. Is there any chance to create this object myself and store in static property?
As you see this is abstract class, so I guess Test Framework is automatically injecting concrete implementation in Scanarios with DI. How could I get this concrete implementation?
If solution is not present, would you suggest another approach how could I store configurable settings besides .runsettings so I could access them in static [BeforeTestRun] method without DI?
Thank you
AFAIK I know the behaviour of TestContext in MSTest, you get in plain MSTest for every test your own instance of TestContext.
So you can't get an instance for the whole testrun.
What you could do is, that you do the HTTP request in the BeforeScenario hook of the first scenario that gets executed. There you can get to the TestContext instance without problems.
I have an ASP.NET Core 2.2 app using EF Core 2.2.
I have some background worker threads which I start in ConfigureServices(). These threads depend on the DbContext and on other services which I register in ConfigureServices().
I found that when I try to use Add-Migration, the EF tools cause these threads to run, which in turn throw exceptions in the Add-Migration output because the threads try to access a database object that does not yet exist.
It appears the migration is created successfully, however, it makes using the tooling difficult because it appears to fail (exceptions in output, process does not exit, etc).
Some options I see to avoid this:-
a) Somehow detect in ConfigureServices() that the database does/does not match the context (i.e. is "up to date") and act accordingly.
b) Start my worker threads somewhere else that will not get invoked when my app is run by the EF tools. Keeping in mind that starting these threads require a ServiceProvider with the same scope I'm building in ConfigureServices().
c) Detect in my app that I'm being called by the EF tools and avoid launching the worker threads.
I'd appreciate any advice on the most appropriate strategy and the best method of achieving it.
EF Core tools use different strategies for creating derived DbContext, explained in the Design-time DbContext Creation section of the documentation.
Looks like currently you are using From application services. But according to the problem explanation, the most appropriate in your case seems to be From a design-time factory:
You can also tell the tools how to create your DbContext by implementing the IDesignTimeDbContextFactory<TContext> interface: If a class implementing this interface is found in either the same project as the derived DbContext or in the application's startup project, the tools bypass the other ways of creating the DbContext and use the design-time factory instead.
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.
I am building a web application, and whenever I make a database call I need a session.
I understand creating a session object is very expensive.
I am following the repository pattern here: http://web.archive.org/web/20110503184234/http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/10/08/the-repository-pattern.aspx
He uses something called a UnitOfWork to get the session.
For a web application, shouldn't I be storing the Session in Request.Items collection? So its only created once per request?
Do I really need UofW?
The session IS the unit of work - its basically used to store changes until you flush them to the db. Save a static session factory at startup, and use that to create one session per web request - Request.Items seems a valid place to put the session.
The repository pattern is a wrapper over the unit of work. The repository pattern differs from the UoW pattern in that repo.Save(obj) should save the obj to the db straight away, while the UoW waits for a flush.
My advice would be to skip the repository pattern and use the ISession directly (see http://ayende.com/Blog/archive/2009/04/17/repository-is-the-new-singleton.aspx)
In the case of NHibernate the key class is the SessionFactory, which SessionProvider is taking care of for you (if you implement it like that). Keep the SessionFactory alive, and it handles the sessions for you.
I've also seem people save the SessionFactory in their IoC.
Use this to manage your sessions:
HybridSessionBuilder
It manages and gives you access to a single session that's used across the entire application.