How to test DB.Configuration.AutoDetectChangesEnabled = false












1














I'm trying to write some tests for a class using NSubstitute.



Class constructor is:



public class ClassToTest : IClassToTest
{
private IDataBase DB;
public ClassToTest(IDatabase DB)
{
this.DB = DB;
this.DB.Configuration.AutoDetectChangesEnabled = false;
}


Here is my UnitTests class:



[TestFixture]
public class ClassToTestUnitTests
{
private ClassToTest _testClass;

[SetUp]
public void SetUp()
{
var Db = Substitute.For<IDatabase>();
//Db.Configuration.AutoDetectChangesEnabled = false; <- I've tried to do it like this

var dummyData = Substitute.For<DbSet<Data>, IQueryable<Data>, IDbAsyncEnumerable<Data>>().SetupData(GetData());

Db.Data.Returns(dummyData);

_testClass = new ClassToTest(Db);
}


Whenever I try to test some method, the test fails and there is a NullReferenceException and it goes in StackTrace to the SetUp method.



When I commented out the
this.DB.Configuration.AutoDetectChangesEnabled = false; in ClassToTest constructor the tests work fine.



Edit:



 public interface IInventoryDatabase
{
DbSet<NamesV> NamesV { get; set; }
DbSet<Adress> Adresses { get; set; }
DbSet<RandomData> Randomdata { get; set; }
// (...more DbSets)

System.Data.Entity.Database Database { get; }
DbContextConfiguration Configuration { get; }
int SaveChanges();
}









share|improve this question
























  • What is the type of Db.Configuration? If it is not an interface or purely virtual class you may need to manually stub out that property: Db.Configuration.Returns(myConfiguration).
    – David Tchepak
    Nov 21 '18 at 22:21












  • @David Tchepak It's of type: System.Data.Entity.Infrastructure.DbContextConfiguration IDataBase.Configuration {get; } Could you show me how that would look like?
    – Alice
    Nov 22 '18 at 8:12












  • From MSDN I can't see a public constructor for this type? In that case I do not think you will be able to stub the Data property. Can you share the IDatabase definition?
    – David Tchepak
    Nov 22 '18 at 22:57










  • @David Tchepak yes, it seems that the lack of constructor is the problem. I've edited the code to show You IDatabase
    – Alice
    Nov 23 '18 at 13:39
















1














I'm trying to write some tests for a class using NSubstitute.



Class constructor is:



public class ClassToTest : IClassToTest
{
private IDataBase DB;
public ClassToTest(IDatabase DB)
{
this.DB = DB;
this.DB.Configuration.AutoDetectChangesEnabled = false;
}


Here is my UnitTests class:



[TestFixture]
public class ClassToTestUnitTests
{
private ClassToTest _testClass;

[SetUp]
public void SetUp()
{
var Db = Substitute.For<IDatabase>();
//Db.Configuration.AutoDetectChangesEnabled = false; <- I've tried to do it like this

var dummyData = Substitute.For<DbSet<Data>, IQueryable<Data>, IDbAsyncEnumerable<Data>>().SetupData(GetData());

Db.Data.Returns(dummyData);

_testClass = new ClassToTest(Db);
}


Whenever I try to test some method, the test fails and there is a NullReferenceException and it goes in StackTrace to the SetUp method.



When I commented out the
this.DB.Configuration.AutoDetectChangesEnabled = false; in ClassToTest constructor the tests work fine.



Edit:



 public interface IInventoryDatabase
{
DbSet<NamesV> NamesV { get; set; }
DbSet<Adress> Adresses { get; set; }
DbSet<RandomData> Randomdata { get; set; }
// (...more DbSets)

System.Data.Entity.Database Database { get; }
DbContextConfiguration Configuration { get; }
int SaveChanges();
}









share|improve this question
























  • What is the type of Db.Configuration? If it is not an interface or purely virtual class you may need to manually stub out that property: Db.Configuration.Returns(myConfiguration).
    – David Tchepak
    Nov 21 '18 at 22:21












  • @David Tchepak It's of type: System.Data.Entity.Infrastructure.DbContextConfiguration IDataBase.Configuration {get; } Could you show me how that would look like?
    – Alice
    Nov 22 '18 at 8:12












  • From MSDN I can't see a public constructor for this type? In that case I do not think you will be able to stub the Data property. Can you share the IDatabase definition?
    – David Tchepak
    Nov 22 '18 at 22:57










  • @David Tchepak yes, it seems that the lack of constructor is the problem. I've edited the code to show You IDatabase
    – Alice
    Nov 23 '18 at 13:39














1












1








1







I'm trying to write some tests for a class using NSubstitute.



Class constructor is:



public class ClassToTest : IClassToTest
{
private IDataBase DB;
public ClassToTest(IDatabase DB)
{
this.DB = DB;
this.DB.Configuration.AutoDetectChangesEnabled = false;
}


Here is my UnitTests class:



[TestFixture]
public class ClassToTestUnitTests
{
private ClassToTest _testClass;

[SetUp]
public void SetUp()
{
var Db = Substitute.For<IDatabase>();
//Db.Configuration.AutoDetectChangesEnabled = false; <- I've tried to do it like this

var dummyData = Substitute.For<DbSet<Data>, IQueryable<Data>, IDbAsyncEnumerable<Data>>().SetupData(GetData());

Db.Data.Returns(dummyData);

_testClass = new ClassToTest(Db);
}


Whenever I try to test some method, the test fails and there is a NullReferenceException and it goes in StackTrace to the SetUp method.



When I commented out the
this.DB.Configuration.AutoDetectChangesEnabled = false; in ClassToTest constructor the tests work fine.



Edit:



 public interface IInventoryDatabase
{
DbSet<NamesV> NamesV { get; set; }
DbSet<Adress> Adresses { get; set; }
DbSet<RandomData> Randomdata { get; set; }
// (...more DbSets)

System.Data.Entity.Database Database { get; }
DbContextConfiguration Configuration { get; }
int SaveChanges();
}









share|improve this question















I'm trying to write some tests for a class using NSubstitute.



Class constructor is:



public class ClassToTest : IClassToTest
{
private IDataBase DB;
public ClassToTest(IDatabase DB)
{
this.DB = DB;
this.DB.Configuration.AutoDetectChangesEnabled = false;
}


Here is my UnitTests class:



[TestFixture]
public class ClassToTestUnitTests
{
private ClassToTest _testClass;

[SetUp]
public void SetUp()
{
var Db = Substitute.For<IDatabase>();
//Db.Configuration.AutoDetectChangesEnabled = false; <- I've tried to do it like this

var dummyData = Substitute.For<DbSet<Data>, IQueryable<Data>, IDbAsyncEnumerable<Data>>().SetupData(GetData());

Db.Data.Returns(dummyData);

_testClass = new ClassToTest(Db);
}


Whenever I try to test some method, the test fails and there is a NullReferenceException and it goes in StackTrace to the SetUp method.



When I commented out the
this.DB.Configuration.AutoDetectChangesEnabled = false; in ClassToTest constructor the tests work fine.



Edit:



 public interface IInventoryDatabase
{
DbSet<NamesV> NamesV { get; set; }
DbSet<Adress> Adresses { get; set; }
DbSet<RandomData> Randomdata { get; set; }
// (...more DbSets)

System.Data.Entity.Database Database { get; }
DbContextConfiguration Configuration { get; }
int SaveChanges();
}






c# unit-testing nsubstitute






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 23 '18 at 12:29

























asked Nov 21 '18 at 15:16









Alice

347




347












  • What is the type of Db.Configuration? If it is not an interface or purely virtual class you may need to manually stub out that property: Db.Configuration.Returns(myConfiguration).
    – David Tchepak
    Nov 21 '18 at 22:21












  • @David Tchepak It's of type: System.Data.Entity.Infrastructure.DbContextConfiguration IDataBase.Configuration {get; } Could you show me how that would look like?
    – Alice
    Nov 22 '18 at 8:12












  • From MSDN I can't see a public constructor for this type? In that case I do not think you will be able to stub the Data property. Can you share the IDatabase definition?
    – David Tchepak
    Nov 22 '18 at 22:57










  • @David Tchepak yes, it seems that the lack of constructor is the problem. I've edited the code to show You IDatabase
    – Alice
    Nov 23 '18 at 13:39


















  • What is the type of Db.Configuration? If it is not an interface or purely virtual class you may need to manually stub out that property: Db.Configuration.Returns(myConfiguration).
    – David Tchepak
    Nov 21 '18 at 22:21












  • @David Tchepak It's of type: System.Data.Entity.Infrastructure.DbContextConfiguration IDataBase.Configuration {get; } Could you show me how that would look like?
    – Alice
    Nov 22 '18 at 8:12












  • From MSDN I can't see a public constructor for this type? In that case I do not think you will be able to stub the Data property. Can you share the IDatabase definition?
    – David Tchepak
    Nov 22 '18 at 22:57










  • @David Tchepak yes, it seems that the lack of constructor is the problem. I've edited the code to show You IDatabase
    – Alice
    Nov 23 '18 at 13:39
















What is the type of Db.Configuration? If it is not an interface or purely virtual class you may need to manually stub out that property: Db.Configuration.Returns(myConfiguration).
– David Tchepak
Nov 21 '18 at 22:21






What is the type of Db.Configuration? If it is not an interface or purely virtual class you may need to manually stub out that property: Db.Configuration.Returns(myConfiguration).
– David Tchepak
Nov 21 '18 at 22:21














@David Tchepak It's of type: System.Data.Entity.Infrastructure.DbContextConfiguration IDataBase.Configuration {get; } Could you show me how that would look like?
– Alice
Nov 22 '18 at 8:12






@David Tchepak It's of type: System.Data.Entity.Infrastructure.DbContextConfiguration IDataBase.Configuration {get; } Could you show me how that would look like?
– Alice
Nov 22 '18 at 8:12














From MSDN I can't see a public constructor for this type? In that case I do not think you will be able to stub the Data property. Can you share the IDatabase definition?
– David Tchepak
Nov 22 '18 at 22:57




From MSDN I can't see a public constructor for this type? In that case I do not think you will be able to stub the Data property. Can you share the IDatabase definition?
– David Tchepak
Nov 22 '18 at 22:57












@David Tchepak yes, it seems that the lack of constructor is the problem. I've edited the code to show You IDatabase
– Alice
Nov 23 '18 at 13:39




@David Tchepak yes, it seems that the lack of constructor is the problem. I've edited the code to show You IDatabase
– Alice
Nov 23 '18 at 13:39












1 Answer
1






active

oldest

votes


















0














The reason for the NullReferenceException is that NSubstitute cannot automatically substitute for DbContextConfiguration (it can only do so for purely virtual classes).



Normally we could work around this by manually configuration this property, something like Db.Configuration.Returns(myConfiguration), but in this case DbContextConfiguration does not seem to have a public constructor so we are unable to create an instance for myConfiguration.



At this stage I can think of two main options: wrap the problematic class in a more testable adapter class; or switch to testing this at a different level. (My preference is the latter which I'll explain below.)



The first option involves something like this:



public interface IDbContextConfiguration {
bool AutoDetectChangesEnabled { get; set; }
// ... any other required members here ...
}

public class DbContextConfigurationAdapter : IDbContextConfiguration {
DbContextConfiguration config;
public DbContextConfigurationAdapter(DbContextConfiguration config) {
this.config = config;
}
public bool AutoDetectChangedEnabled {
get { return config.AutoDetectChangedEnabled; }
set { config = value; }
}
}


Then updating IInventoryDatabase to using the more testable IDbContextConfiguration type. My opposition to this approach is that it can end up requiring a lot of work for something that should be fairly simple. This approach can be very useful for cases where we have behaviours that make sense to be grouped under a logical interface, but for working with an AutoDetectChangedEnabled property this seems unnecessary work.



The other option is to test this at a different level. I think the friction in testing the current code is that we are trying to substitute for details of Entity Framework, rather than interfaces we've created for partitioning the logical details of our app. Search for "don't mock types you don't own" for more information on why this can be a problem (I've written about it before here).



One example of testing at a different level is to switch to an in-memory database for testing this part of the code. This will tell you much more valuable information: given a known state of the test database, you are demonstrating the queries return the expected information. This is in contrast to a test showing we are calling Entity Framework in the way we think is required.



To combine this approach with mocking (not necessarily required!), we can create a higher level interface and substitute for that for testing our application code, then make an implementation of that interface and test that using the in-memory database. We have then divided the application into two parts that we can test independently: first that our app uses data from the data access interface correctly, and secondly that our implementation of that interface works as expected.



So that would give us something like this:



public interface IAppDatabase {
// These members just for example. Maybe instead of something general like
// `GetAllNames()` we have operations specific to app operations such as
// `UpdateAddress(Guid id, Address newAddress)`, `GetNameFor(SomeParams p)` etc.
Task<List<Name>> GetAllNames();
Task<Address> LookupAddress(Guid id);
}

public class AppDatabase : IAppDatabase {
// ...
public AppDatabase(IInventoryDatabase db) { ... }

public Task<List<Name>> GetAllNames() {
// use `db` and Entity Framework to retrieve data...
}
// ...
}


The AppDatabase class we test with an in-memory database. The rest of the app we test with respect to a substitute IAppDatabase.



Note that we can skip the mocking step here by using the in-memory database for all relevant tests. Using mocking may be easier than setting up all the required data in the database, or may make tests run faster. Or maybe not -- I suggest considering both options.



Hope this helps.






share|improve this answer





















    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53415138%2fhow-to-test-db-configuration-autodetectchangesenabled-false%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0














    The reason for the NullReferenceException is that NSubstitute cannot automatically substitute for DbContextConfiguration (it can only do so for purely virtual classes).



    Normally we could work around this by manually configuration this property, something like Db.Configuration.Returns(myConfiguration), but in this case DbContextConfiguration does not seem to have a public constructor so we are unable to create an instance for myConfiguration.



    At this stage I can think of two main options: wrap the problematic class in a more testable adapter class; or switch to testing this at a different level. (My preference is the latter which I'll explain below.)



    The first option involves something like this:



    public interface IDbContextConfiguration {
    bool AutoDetectChangesEnabled { get; set; }
    // ... any other required members here ...
    }

    public class DbContextConfigurationAdapter : IDbContextConfiguration {
    DbContextConfiguration config;
    public DbContextConfigurationAdapter(DbContextConfiguration config) {
    this.config = config;
    }
    public bool AutoDetectChangedEnabled {
    get { return config.AutoDetectChangedEnabled; }
    set { config = value; }
    }
    }


    Then updating IInventoryDatabase to using the more testable IDbContextConfiguration type. My opposition to this approach is that it can end up requiring a lot of work for something that should be fairly simple. This approach can be very useful for cases where we have behaviours that make sense to be grouped under a logical interface, but for working with an AutoDetectChangedEnabled property this seems unnecessary work.



    The other option is to test this at a different level. I think the friction in testing the current code is that we are trying to substitute for details of Entity Framework, rather than interfaces we've created for partitioning the logical details of our app. Search for "don't mock types you don't own" for more information on why this can be a problem (I've written about it before here).



    One example of testing at a different level is to switch to an in-memory database for testing this part of the code. This will tell you much more valuable information: given a known state of the test database, you are demonstrating the queries return the expected information. This is in contrast to a test showing we are calling Entity Framework in the way we think is required.



    To combine this approach with mocking (not necessarily required!), we can create a higher level interface and substitute for that for testing our application code, then make an implementation of that interface and test that using the in-memory database. We have then divided the application into two parts that we can test independently: first that our app uses data from the data access interface correctly, and secondly that our implementation of that interface works as expected.



    So that would give us something like this:



    public interface IAppDatabase {
    // These members just for example. Maybe instead of something general like
    // `GetAllNames()` we have operations specific to app operations such as
    // `UpdateAddress(Guid id, Address newAddress)`, `GetNameFor(SomeParams p)` etc.
    Task<List<Name>> GetAllNames();
    Task<Address> LookupAddress(Guid id);
    }

    public class AppDatabase : IAppDatabase {
    // ...
    public AppDatabase(IInventoryDatabase db) { ... }

    public Task<List<Name>> GetAllNames() {
    // use `db` and Entity Framework to retrieve data...
    }
    // ...
    }


    The AppDatabase class we test with an in-memory database. The rest of the app we test with respect to a substitute IAppDatabase.



    Note that we can skip the mocking step here by using the in-memory database for all relevant tests. Using mocking may be easier than setting up all the required data in the database, or may make tests run faster. Or maybe not -- I suggest considering both options.



    Hope this helps.






    share|improve this answer


























      0














      The reason for the NullReferenceException is that NSubstitute cannot automatically substitute for DbContextConfiguration (it can only do so for purely virtual classes).



      Normally we could work around this by manually configuration this property, something like Db.Configuration.Returns(myConfiguration), but in this case DbContextConfiguration does not seem to have a public constructor so we are unable to create an instance for myConfiguration.



      At this stage I can think of two main options: wrap the problematic class in a more testable adapter class; or switch to testing this at a different level. (My preference is the latter which I'll explain below.)



      The first option involves something like this:



      public interface IDbContextConfiguration {
      bool AutoDetectChangesEnabled { get; set; }
      // ... any other required members here ...
      }

      public class DbContextConfigurationAdapter : IDbContextConfiguration {
      DbContextConfiguration config;
      public DbContextConfigurationAdapter(DbContextConfiguration config) {
      this.config = config;
      }
      public bool AutoDetectChangedEnabled {
      get { return config.AutoDetectChangedEnabled; }
      set { config = value; }
      }
      }


      Then updating IInventoryDatabase to using the more testable IDbContextConfiguration type. My opposition to this approach is that it can end up requiring a lot of work for something that should be fairly simple. This approach can be very useful for cases where we have behaviours that make sense to be grouped under a logical interface, but for working with an AutoDetectChangedEnabled property this seems unnecessary work.



      The other option is to test this at a different level. I think the friction in testing the current code is that we are trying to substitute for details of Entity Framework, rather than interfaces we've created for partitioning the logical details of our app. Search for "don't mock types you don't own" for more information on why this can be a problem (I've written about it before here).



      One example of testing at a different level is to switch to an in-memory database for testing this part of the code. This will tell you much more valuable information: given a known state of the test database, you are demonstrating the queries return the expected information. This is in contrast to a test showing we are calling Entity Framework in the way we think is required.



      To combine this approach with mocking (not necessarily required!), we can create a higher level interface and substitute for that for testing our application code, then make an implementation of that interface and test that using the in-memory database. We have then divided the application into two parts that we can test independently: first that our app uses data from the data access interface correctly, and secondly that our implementation of that interface works as expected.



      So that would give us something like this:



      public interface IAppDatabase {
      // These members just for example. Maybe instead of something general like
      // `GetAllNames()` we have operations specific to app operations such as
      // `UpdateAddress(Guid id, Address newAddress)`, `GetNameFor(SomeParams p)` etc.
      Task<List<Name>> GetAllNames();
      Task<Address> LookupAddress(Guid id);
      }

      public class AppDatabase : IAppDatabase {
      // ...
      public AppDatabase(IInventoryDatabase db) { ... }

      public Task<List<Name>> GetAllNames() {
      // use `db` and Entity Framework to retrieve data...
      }
      // ...
      }


      The AppDatabase class we test with an in-memory database. The rest of the app we test with respect to a substitute IAppDatabase.



      Note that we can skip the mocking step here by using the in-memory database for all relevant tests. Using mocking may be easier than setting up all the required data in the database, or may make tests run faster. Or maybe not -- I suggest considering both options.



      Hope this helps.






      share|improve this answer
























        0












        0








        0






        The reason for the NullReferenceException is that NSubstitute cannot automatically substitute for DbContextConfiguration (it can only do so for purely virtual classes).



        Normally we could work around this by manually configuration this property, something like Db.Configuration.Returns(myConfiguration), but in this case DbContextConfiguration does not seem to have a public constructor so we are unable to create an instance for myConfiguration.



        At this stage I can think of two main options: wrap the problematic class in a more testable adapter class; or switch to testing this at a different level. (My preference is the latter which I'll explain below.)



        The first option involves something like this:



        public interface IDbContextConfiguration {
        bool AutoDetectChangesEnabled { get; set; }
        // ... any other required members here ...
        }

        public class DbContextConfigurationAdapter : IDbContextConfiguration {
        DbContextConfiguration config;
        public DbContextConfigurationAdapter(DbContextConfiguration config) {
        this.config = config;
        }
        public bool AutoDetectChangedEnabled {
        get { return config.AutoDetectChangedEnabled; }
        set { config = value; }
        }
        }


        Then updating IInventoryDatabase to using the more testable IDbContextConfiguration type. My opposition to this approach is that it can end up requiring a lot of work for something that should be fairly simple. This approach can be very useful for cases where we have behaviours that make sense to be grouped under a logical interface, but for working with an AutoDetectChangedEnabled property this seems unnecessary work.



        The other option is to test this at a different level. I think the friction in testing the current code is that we are trying to substitute for details of Entity Framework, rather than interfaces we've created for partitioning the logical details of our app. Search for "don't mock types you don't own" for more information on why this can be a problem (I've written about it before here).



        One example of testing at a different level is to switch to an in-memory database for testing this part of the code. This will tell you much more valuable information: given a known state of the test database, you are demonstrating the queries return the expected information. This is in contrast to a test showing we are calling Entity Framework in the way we think is required.



        To combine this approach with mocking (not necessarily required!), we can create a higher level interface and substitute for that for testing our application code, then make an implementation of that interface and test that using the in-memory database. We have then divided the application into two parts that we can test independently: first that our app uses data from the data access interface correctly, and secondly that our implementation of that interface works as expected.



        So that would give us something like this:



        public interface IAppDatabase {
        // These members just for example. Maybe instead of something general like
        // `GetAllNames()` we have operations specific to app operations such as
        // `UpdateAddress(Guid id, Address newAddress)`, `GetNameFor(SomeParams p)` etc.
        Task<List<Name>> GetAllNames();
        Task<Address> LookupAddress(Guid id);
        }

        public class AppDatabase : IAppDatabase {
        // ...
        public AppDatabase(IInventoryDatabase db) { ... }

        public Task<List<Name>> GetAllNames() {
        // use `db` and Entity Framework to retrieve data...
        }
        // ...
        }


        The AppDatabase class we test with an in-memory database. The rest of the app we test with respect to a substitute IAppDatabase.



        Note that we can skip the mocking step here by using the in-memory database for all relevant tests. Using mocking may be easier than setting up all the required data in the database, or may make tests run faster. Or maybe not -- I suggest considering both options.



        Hope this helps.






        share|improve this answer












        The reason for the NullReferenceException is that NSubstitute cannot automatically substitute for DbContextConfiguration (it can only do so for purely virtual classes).



        Normally we could work around this by manually configuration this property, something like Db.Configuration.Returns(myConfiguration), but in this case DbContextConfiguration does not seem to have a public constructor so we are unable to create an instance for myConfiguration.



        At this stage I can think of two main options: wrap the problematic class in a more testable adapter class; or switch to testing this at a different level. (My preference is the latter which I'll explain below.)



        The first option involves something like this:



        public interface IDbContextConfiguration {
        bool AutoDetectChangesEnabled { get; set; }
        // ... any other required members here ...
        }

        public class DbContextConfigurationAdapter : IDbContextConfiguration {
        DbContextConfiguration config;
        public DbContextConfigurationAdapter(DbContextConfiguration config) {
        this.config = config;
        }
        public bool AutoDetectChangedEnabled {
        get { return config.AutoDetectChangedEnabled; }
        set { config = value; }
        }
        }


        Then updating IInventoryDatabase to using the more testable IDbContextConfiguration type. My opposition to this approach is that it can end up requiring a lot of work for something that should be fairly simple. This approach can be very useful for cases where we have behaviours that make sense to be grouped under a logical interface, but for working with an AutoDetectChangedEnabled property this seems unnecessary work.



        The other option is to test this at a different level. I think the friction in testing the current code is that we are trying to substitute for details of Entity Framework, rather than interfaces we've created for partitioning the logical details of our app. Search for "don't mock types you don't own" for more information on why this can be a problem (I've written about it before here).



        One example of testing at a different level is to switch to an in-memory database for testing this part of the code. This will tell you much more valuable information: given a known state of the test database, you are demonstrating the queries return the expected information. This is in contrast to a test showing we are calling Entity Framework in the way we think is required.



        To combine this approach with mocking (not necessarily required!), we can create a higher level interface and substitute for that for testing our application code, then make an implementation of that interface and test that using the in-memory database. We have then divided the application into two parts that we can test independently: first that our app uses data from the data access interface correctly, and secondly that our implementation of that interface works as expected.



        So that would give us something like this:



        public interface IAppDatabase {
        // These members just for example. Maybe instead of something general like
        // `GetAllNames()` we have operations specific to app operations such as
        // `UpdateAddress(Guid id, Address newAddress)`, `GetNameFor(SomeParams p)` etc.
        Task<List<Name>> GetAllNames();
        Task<Address> LookupAddress(Guid id);
        }

        public class AppDatabase : IAppDatabase {
        // ...
        public AppDatabase(IInventoryDatabase db) { ... }

        public Task<List<Name>> GetAllNames() {
        // use `db` and Entity Framework to retrieve data...
        }
        // ...
        }


        The AppDatabase class we test with an in-memory database. The rest of the app we test with respect to a substitute IAppDatabase.



        Note that we can skip the mocking step here by using the in-memory database for all relevant tests. Using mocking may be easier than setting up all the required data in the database, or may make tests run faster. Or maybe not -- I suggest considering both options.



        Hope this helps.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 26 '18 at 0:17









        David Tchepak

        6,8123248




        6,8123248






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53415138%2fhow-to-test-db-configuration-autodetectchangesenabled-false%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Contact image not getting when fetch all contact list from iPhone by CNContact

            count number of partitions of a set with n elements into k subsets

            A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks