Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DbConnection without Db using in-memory DataSet (or similar) as source

I'm trying to unit test a few .NET classes that (for good design reasons) require DbConnections to do their work. For these tests, I have certain data in memory to give as input to these classes.

That in-memory data could be easily expressed as a DataTable (or a DataSet that contains that DataTable), but if another class were more appropriate I could use it.

If I were somehow magically able to get a DbConnection that represented a connection to the in-memory data, then I could construct my objects, have them execute their queries against the in-memory data, and ensure that their output matched expectations. Is there some way to get a DbConnection to in-memory data? I don't have the freedom to install any additional third-party software to make this happen, and ideally, I don't want to touch the disk during the tests.

like image 758
Jerry Federspiel Avatar asked Mar 25 '09 20:03

Jerry Federspiel


People also ask

How do I retrieve data from a dbconnection object?

This example takes a DbConnection object as an argument. A DbCommand is created to select data from the Categories table by setting the CommandText to a SQL SELECT statement. The code assumes that the Categories table exists at the data source. The connection is opened and the data is retrieved using a DbDataReader.

What is dbconnection in SQL Server?

Defines the core behavior of database connections and provides a base class for database-specific connections. public abstract class DbConnection : IDisposable, System. Data. IDbConnection

How do I use dbproviderfactory and dbconnection?

Once you have created a DbProviderFactory and a DbConnection, you can then work with commands and data readers to retrieve data from the data source. This example takes a DbConnection object as an argument.

What are the required properties of a dbconnection?

You must also provide the following properties: ConnectionString, Database, DataSource, ServerVersion, and State. Initializes a new instance of the DbConnection class. Gets a value indicating whether the component can raise an event.


2 Answers

Rather than consume a DbConnection can you consume IDbConnection and mock it? We do something similar, pass the mock a DataSet. DataSet.CreateDataReader returns a DataTableReader which inherits from DbDataReader.

We have wrapped DbConnection in our own IDbConnection-like interface to which we've added an ExecuteReader() method which returns a class that implements the same interfaces as DbDataReader. In our mock, ExecuteReader simply returns what DataSet.CreateDataReader serves up.

Sounds kind of roundabout, but it is very convenient to build up a DataSet with possibly many resultsets. We name the DataTables after the stored procs that they represent the results of, and our IDbConnection mock grabs the right Datatable based on the proc the client is calling. DataTable also implements CreateDataReader so we're good to go.

like image 118
n8wrl Avatar answered Nov 02 '22 12:11

n8wrl


An approach that I've used is to create an in-memory Sqlite database. This may be done simply by pulling in the System.Data.SQLite.Core NuGet package to your unit test project, you don't need to install any software anywhere else.

Although it sounds like a really obvious idea, it wasn't until I was looking at the Dapper unit tests that I thought to use the technique myself! See the "GetSqliteConnection" method in

https://github.com/StackExchange/dapper-dot-net/blob/bffb0972a076734145d92959dabbe48422d12922/Dapper.Tests/Tests.cs

One thing to be aware of is that if you create an in-memory sqlite db and create and populate tables, you need to be careful not to close the connection before performing your test queries because opening a new in-memory connection will get you a connection to a new in-memory database, not the database that you just carefully prepared for your tests! For some of my tests, I use a custom IDbConnection implementation that keeps the connection open to avoid this pitfall - eg.

https://github.com/ProductiveRage/SqlProxyAndReplay/blob/master/Tests/StaysOpenSqliteConnection.cs

like image 33
Dan Roberts Avatar answered Nov 02 '22 10:11

Dan Roberts