It is code in assembly EPiServer.Framework.AspNet that is responsible to read data from config and populate DataAccessOptions. So either you add that assembly to your list or you can have a module in your integration test project with code as:
public void ConfigureContainer(ServiceConfigurationContext context)
{
context.Services.Configure<DataAccessOptions>(o =>
{
o.CreateDatabaseSchema = true;
o.UpdateDatabaseSchema = true;
o.SetConnectionString(<yourconnectionstring>);
});
}
Thank you!
I have such a InitializationModule
— without the options, trying an reset before, restore after approach (such as https://blog.mathiaskunto.com/2016/11/25/keeping-reliable-test-data-in-episerver-content-database-for-automated-ui-tests/), testing the Alloy site as a starter.
It doesn’t seem to be initiated though.
Will look into the other option when I can. 👍
I made some progress, regarding getting forward from the error I had, when adding EPiServer.Framework.AspNet
, but then I hade to add another assembly for the next error, and another assembly etc, and the more I added, the more complex things got, and I still ended up with the same issue, the InitializableModule
isn't loaded etc.!
I ended up with this:
var data = Assembly.GetAssembly(typeof(EPiServer.Data.DataInitialization));
var events = Assembly.GetAssembly(typeof(EPiServer.Events.EventMessage));
var framework = Assembly.GetAssembly(typeof(EPiServer.Framework.EnvironmentOptions));
var frameworkAspnet = Assembly.GetAssembly(typeof(EPiServer.Framework.Web.AspNetAntiForgery));
var epiServerCmsCore = Assembly.GetAssembly(typeof(EPiServer.DeleteContentEventArgs));
var cmsAspnet = Assembly.GetAssembly(typeof(EPiServer.Web.InitializationModule));
var epiServerEnterprise = Assembly.GetAssembly(typeof(EPiServer.Enterprise.ContentExportedEventArgs));
var structureMap = Assembly.GetAssembly(typeof(EPiServer.ServiceLocation.StructureMapServiceLocator));
var applicationModules = Assembly.GetAssembly(typeof(EPiServer.Personalization.VisitorGroups.VisitorGroupOptions));
var linkAnalyzer = Assembly.GetAssembly(typeof(EPiServer.LinkAnalyzer.LinkValidatorOptions));
var _engine = new InitializationEngine((IEnumerable<IInitializableModule>)null, HostType.TestFramework,
new List <Assembly> {
data,
events,
cmsAspnet,
framework,
// crucial?frameworkAspnet,
linkAnalyzer,
applicationModules,
epiServerCmsCore, // crucial?
epiServerEnterprise,
structureMap // crucial?
});
_engine.Initialize();
This leads me (as always) wanting the minimal setup possible, preferable only EPiServer.Framework
, EPiServer.CMS.Core
and EPiServer.ServiceLocation.StructureMap
.
The issue I'm back to now is why my InitializableModule
isn't executed before the errors about the connectionstring
or that the database does not exist in the bin directory (the InitializableModule
should correct that if loaded correctly):
[InitializableModule]
[ModuleDependency(typeof(CmsCoreInitialization))]
public class Initialization : IConfigurableModule
{
public void ConfigureContainer(ServiceConfigurationContext context)
{
// Configure the database access
context.Services.Configure<DataAccessOptions>(o =>
{
//getting the physical path of Alloy-web-root
var webAppPath = IISExpressHostFactory.GetApplicationPath();
var originalConnectionString = ConfigurationManager.ConnectionStrings["EPiServerDB"].ConnectionString;
var absolutePathConnectionString = originalConnectionString.Replace("|DataDirectory|", Path.Combine(webAppPath, "App_Data") + "\\");
o.SetConnectionString(absolutePathConnectionString);
// in my case: "Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=C:\EPiServer\TestDrive\TestDrive.Web\App_Data\EPiServerDB_1fe05723.mdf;Initial Catalog=EPiServerDB_1fe05723;Connection Timeout=60;Integrated Security=True;MultipleActiveResultSets=True"
});
}
void IInitializableModule.Initialize(InitializationEngine context) { }
void IInitializableModule.Uninitialize(InitializationEngine context) { }
}
Isn't the InitializationEngine
and related assemblies supposed to run the InitializableModule
:s accordingly if this module is existing in the running assembly without any more configuration?
My only need is to create Pages
and Blocks
by code using IContentRepository
, on a database that is not hard coded but changed in an InitializableModule
. So I need only the basic stuff.
I'm I right that we no longer have to put most of the web.config
parts in app.config
when initializing this way, I'm on the right path?
The provided code in this comment is the only code I wrote for the EPi initialization part – is there anything obvious I might be missing?
If you pass in assemblies to InitializationEngine then it will only scan those assemblies for modules. So you should add your test assembly to the scanning. E.g like this.GetType().Assembly
Thank you!
At last I got things to work!
var data = Assembly.GetAssembly(typeof(EPiServer.Data.DataInitialization));
var events = Assembly.GetAssembly(typeof(EPiServer.Events.EventMessage));
var framework = Assembly.GetAssembly(typeof(EPiServer.Framework.EnvironmentOptions));
var epiServerCmsCore = Assembly.GetAssembly(typeof(EPiServer.DeleteContentEventArgs));
var epiServerEnterprise = Assembly.GetAssembly(typeof(EPiServer.Enterprise.ContentExportedEventArgs));
var structureMap = Assembly.GetAssembly(typeof(EPiServer.ServiceLocation.StructureMapServiceLocator));
var applicationModules = Assembly.GetAssembly(typeof(EPiServer.Personalization.VisitorGroups.VisitorGroupOptions));
//var frameworkAspnet = Assembly.GetAssembly(typeof(EPiServer.Framework.Web.AspNetAntiForgery));
//var cmsAspnet = Assembly.GetAssembly(typeof(EPiServer.Web.InitializationModule));//var linkAnalyzer = Assembly.GetAssembly(typeof(EPiServer.LinkAnalyzer.LinkValidatorOptions));
var _engine = new InitializationEngine((IEnumerable<IInitializableModule>)null, HostType.TestFramework,
new List <Assembly> {
data,
events,
framework,
applicationModules,
epiServerCmsCore,
epiServerEnterprise,
structureMap,
Assembly.GetExecutingAssembly(),
//frameworkAspnet,
//linkAnalyzer,
//cmsAspnet,});
_engine.Initialize();
The above was the minimal working setup I could come up with, had to remove some parts but keep others, by different reasons. Like virtualPath
could not be null etc. (probably a EPiServer.Framework.AspNet
related issue)
Now I only have test assertion issues, the things I didn't finnish due to the problems initiating the framework. 👍
Thank you Johan for your support, I've learned what I can do and that this code actually works in my setup. Hopefully someone else with similar issues can find some angles or solutions to their problems.
Now I can continue testing how I would like to improve the workflow and quality work when building EPiServer webs.
I thought it might be a better way to do blacklist instead of a whitelist.
One of the issues for me was getting a lot of dependencies I didn't want in my bin-folder since I referenced the Alloy-project and got all its dependencies.
At least a blacklist gives me more control of what I am excluding.
var blacklist = new[] {
typeof(NUnit.Framework.ApartmentAttribute).Assembly,
Assembly.Load("NUnit3.TestAdapter"),
Assembly.Load("EPiServer.Find"),
Assembly.Load("EPiServer.Find.Cms"),
Assembly.Load("EPiServer.Find.Framework"),
Assembly.Load("EPiServer.Find.UI"),
Assembly.Load("EPiServer.Framework.AspNet"),
Assembly.Load("EPiServer.Cms.AspNet"),
Assembly.Load("EPiServer.Cms.Shell.UI"),
Assembly.Load("EPiServer.LinkAnalyzer"),
Assembly.Load("EPiServer.Shell"),
Assembly.Load("EPiServer.Shell.UI"),
Assembly.Load("EPiServer.Cms.TinyMce"),
Assembly.Load("EPiServer.Cms.UI.AspNetIdentity"),
Assembly.Load("EPiServer.UI"),
typeof(Web.Global).Assembly,
}.ToEnumerable();
var _engine = new InitializationEngine(
(IEnumerable<IInitializableModule>)null,
HostType.TestFramework,
new AssemblyList(true).AllowedAssemblies.Except(blacklist));
_engine.Initialize();
Do you think this is a more future safe way of doing things?
Hi,
I followed the guidelines by @henriknystrom at https://thisisnothing.nystrom.co.nz/2017/12/05/integration-testing-with-episerver/ refered to in this closed thread: https://world.episerver.com/Modules/Forum/Pages/Thread.aspx?id=185646
I'm trying out some Integration testing, using NUnit 3 and SpecFlow, IIS Express and Selenium.
When calling:
I get a failure that seems to be related to this: https://github.com/Microsoft/vstest/issues/1417
So, basically I should not be reflecting types from
Microsoft.VisualStudio.TestPlatform.ObjectModel
.Therefore I tried something like this:
But it´s not getting me the whole way, some error about no connectionstrings is found etc. (I have the connectionstring in my
app.config
, and I have aInitializationModule
setting the connectionstring up configuringDataAccessOptions
)Does anyone know exactly which assemblies are needed to setup EPi CMS for testing or how I could use
new AssemblyList(true).AllowedAssemblies
and instead excludeMicrosoft.VisualStudio.TestPlatform.ObjectModel
?Guess things starts working when all needed assemblies are loaded and the initialization modules are run correctly, without some buggy assembly comes interfering and ruining my geeky party. @henriknystrom - can you please shed some light on this for me!? ;)