-1

We have some integration/unit tests to validate our NHibernate mappings. I introduced some data driven tests that utilize the [DeploymentItem] attribute above the test methods to import a CSV file. The mere existence of this attribute in any test in the unit test project causes all of the NHibernate mapping tests to fail with the message below:

Error Message:
   Initialization method UnitTests.SearchOrganizationTests.Setup threw exception. NHibernate.HibernateException: NHibernate.HibernateException: Could not create the driver from NHibernate.Driver.OracleDataClientDriver. ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object..
Stack Trace:
    at NHibernate.Driver.OracleDataClientDriver..ctor()
 --- End of inner exception stack trace ---
    at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
   at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
   at System.Activator.CreateInstance(Type type)
   at NHibernate.Bytecode.ActivatorObjectsFactory.CreateInstance(Type type)
   at NHibernate.Connection.ConnectionProvider.ConfigureDriver(IDictionary`2 settings)
 --- End of inner exception stack trace ---
    at NHibernate.Connection.ConnectionProvider.ConfigureDriver(IDictionary`2 settings)
   at NHibernate.Connection.ConnectionProvider.Configure(IDictionary`2 settings)
   at NHibernate.Connection.ConnectionProviderFactory.NewConnectionProvider(IDictionary`2 settings)
   at NHibernate.Cfg.SettingsFactory.BuildSettings(IDictionary`2 properties)
   at NHibernate.Cfg.Configuration.BuildSettings()
   at NHibernate.Cfg.Configuration.BuildSessionFactory()
   at MyApplication.DataContext.get_SessionFactory()
   at MyApplication.DataContext.GetClassMetadata(Type type)
   at MyApplication.DataContext.GetClassMetadata[T]()
   at MyApplication.DataContext.GetTableName[T]()

I get the same failure whether I use mstest.exe or vstest.console.exe from the command line.

Running the tests from the "Test Explorer" in Visual Studio 2013 works just fine. Running the tests from the command line fails, which is a problem for our continuous integration server.

So additional info:

  • It's a Unit Test project in Visual Studio
  • The Oracle.DataAccess.dll file is in the build output directory (and "Copy Local" is set to "True") only when I do not run tests decorated with the [DeploymentItem] attribute
  • When running at least 1 test decorated with the [DeploymentItem] attribute, the Oracle.DataAccess.dll file does not get copied to the output directory
  • The "Copy to Output" property for all the CSV files is set to "Always"
  • Visual Studio 2013
  • NHibernate version 4.0.4.4000
  • .NET 4.5.1
  • FluentNHibernate version 2.0.3.0
  • Oracle client 12c is installed on my machine (12.1.0)

Update #1: I looked in the TestResults/<Test run name>/Out directory, and I don't see the Oracle.DataAccess.dll file


Update #2: We have a test that opens a connection to an Oracle database directly using the Oracle client library. I added a [DeploymentItem] attribute above this test referencing the Oracle.DataAccess.dll file. Now the NHibernate mapping tests are passing, but the data driven tests are not loading the CSV files.

[TestClass]
public class OracleConnectionTests
{
    [TestMethod]
    [TestProperty("Data Mappings", "Connection Test")]
    [DeploymentItem(@"..\Dependencies\Oracle.DataAccess.dll")]
    public void CanOpenCloseConnection()
    {
        OracleConnection oraConn = new OracleConnection("connection string here");
        oraConn.Open();
        Assert.IsTrue(oraConn.State == ConnectionState.Open);
        oraConn.Close();
        Assert.IsFalse(oraConn.State == ConnectionState.Open);
    }
}

A sample data driven test:

[TestClass]
public class FixedPrologueTests
{
    private const string DATA_PROVIDER = "Microsoft.VisualStudio.TestTools.DataSource.CSV";
    private const string DATA_FILE_PATH = @".\UnitTests\ViewModelTests\FixedPrologueTestData.csv";
    private const string DATA_OUTPUT_PATH = @"UnitTests\ViewModelTests";
    private const string DATA_TABLE_NAME = "FixedPrologueTestData.csv";

    public TestContext TestContext { get; set; }

    private PaginationPrologueTestData data;
    private PaginationPrologue prologue;
    private System.Collections.Generic.IEnumerable<int> epilogue;

    [TestInitialize]
    public void Setup()
    {
        data = new PaginationPrologueTestData(TestContext.DataRow);
        prologue = new PaginationPrologue(data.Padding, data.CurrentPage, data.TotalPages);
        epilogue = prologue.CreateEpilogue();
    }

    [TestMethod]
    [TestProperty("PaginationPrologue", "Prologue remains fixed when nearing end of result set")]
    [DataSource(DATA_PROVIDER, DATA_FILE_PATH, DATA_TABLE_NAME, DataAccessMethod.Sequential)]
    [DeploymentItem(DATA_FILE_PATH, DATA_OUTPUT_PATH)]
    public void WhenNearingEndOfResultSet_EpilogueIsNotIncluded()
    {
        Assert.AreEqual(data.EpilogueLength, epilogue.Count());
    }

How can I include the [DeploymentItem] attribute to allow data driven tests to load the CSV files, and allow NHibernate to load the Oracle driver when running tests from the command line?

Greg Burghardt
  • 17,900
  • 9
  • 49
  • 92
  • NHibernate does [dynamically load](https://github.com/nhibernate/nhibernate-core/blob/master/src/NHibernate/Util/ReflectHelper.cs#L395) the Oracle driver dependencies. If it is unable to find them, it fails as you see. You have to ensure the assemblies are either in the application output directory (with the adequate bitness if relevant), or in the GAC. – Frédéric May 26 '17 at 15:18
  • @Frédéric: The Oracle assemblies get included in the output directory *until* you run a test annotated with the `[DeployementItem]` attribute. Then the Oracle assemblies do not get copied to the output directory, despite the "Copy Local" property in Visual Studio being set to "True". – Greg Burghardt May 26 '17 at 15:46
  • @Frédéric: I've updated my question with that tidbit of information. I thought I had included it before, but I didn't. – Greg Burghardt May 26 '17 at 15:48
  • Quite a strange issue. I do not know why running a test with that attribute would remove things from output. Since it is a dynamically loaded assembly, you may remove it from the references and simply add it as a file with `Copy to output directory` option, to check if that changes anything. Otherwise GAC it and use `` element in the application configuration file to specify the full name of the assembly. Or add a [resolve event](https://github.com/nhibernate/nhibernate-core/blob/master/src/NHibernate.Test/TestConfigurationHelper.cs#L24) to load it from somewhere else. – Frédéric May 26 '17 at 16:01

1 Answers1

0

I ended up "fixing" this with a compiler flag:

    [TestMethod]
    [TestProperty("PaginationPrologue", "Prologue remains fixed when nearing end of result set")]
    [DataSource(DATA_PROVIDER, DATA_FILE_PATH, DATA_TABLE_NAME, DataAccessMethod.Sequential)]
#IF DEPLOY_TEST_DATA
    [DeploymentItem(DATA_FILE_PATH, DATA_OUTPUT_PATH)]
#ENDIF
    public void WhenNearingEndOfResultSet_EpilogueIsNotIncluded()
    {
        Assert.AreEqual(data.EpilogueLength, epilogue.Count());
    }

Since this error occurred only when running automated tests on our build server, this was a good-enough fix. To be honest I'm still not sure why this works, I just know it does. It's been over 3 years and things have been pretty stable.

Greg Burghardt
  • 17,900
  • 9
  • 49
  • 92