I have two test cases: UserTest and CustomerTest, both of them extend the AbstractTransactionalSpringContextTests, they are using the same config file, so I wrote a BaseSpringTest class:
public class BaseSpringTest : AbstractTransactionalDbProviderSpringContextTests
{
static protected string ctxName = "application_context.xml";
static protected string[] configlocation = new string[] { "
assembly://test/test.config/" + ctxName};
protected override string[] ConfigLocations
{
get
{
return configlocation;
}
}
}
public class UserTest : BaseSpringTest
{
//test case ...
}
public class CustomerTest : BaseSpringTest
{
//test case ...
}
When I run the tests, it throws an exception:
Spring.Objects.Factory.ObjectCreationException : Error creating object with name 'xxxService' defined in 'assembly [Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null], resource [test.config.Service.xml]' : Initialization of object failed : Duplicate type name within an assembly.
----> System.ArgumentException : Duplicate type name within an assembly.
I traced into AbstractSpringContextTests class and found that it's using a hashtable to cache the loaded context, but the hashtable isn't a static field:
private IDictionary contextKeyToContextMap = new Hashtable();
So the problem is it load the context and put to the hashtable, but the hashtable is only available in the same class, when the nunit run the second test, the hashtable is empty again, so it try to load the context again, then the exception occurs.
So I think just change the hashtable to static is ok.
and what I'm doing now is to cache the context again in my baseSpringTest class which needn't to be that:
public class BaseSpringTest : AbstractTransactionalDbProviderSpringContextTests
{
static protected string ctxName = "application_context.xml";
static protected string[] configlocation = new string[] { "
assembly://NewGarman.Service/com.newgarman.config/" + ctxName};
static protected IConfigurableApplicationContext cachedApplicationContext = null;
protected override string[] ConfigLocations
{
get
{
return configlocation;
}
}
[SetUp]
public new void SetUp()
{
if (cachedApplicationContext == null)
{
XmlConfigurator.Configure();
base.SetUp();
cachedApplicationContext = applicationContext;
}
applicationContext = cachedApplicationContext;
EndTransaction();
InjectDependencies();
try
{
OnSetUp();
}
catch (Exception ex)
{
logger.Error("Setup error", ex);
throw;
}
}
}
Spring.net is a great work, but why this bug keeps so long time, and nobody submit it?
anyway, thanks very much for spring and spring.net.
The context dictionary should certainly be static but I don't see the side effect you are talking about, i.e.
Spring.Objects.Factory.ObjectCreationException : Error creating object with name 'xxxService' defined in 'assembly [Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null], resource [test.config.Service.xml]' : Initialization of object failed : Duplicate type name within an assembly.
The current test cases that I have were simply loading the context over and over again, so no caching, but they still worked. I never noticed the slowdown in speed since I turn logging off for Spring.Core etc., for these tests.
I've changed the dictionary to static and you can pick it up in the next daily download.