Nsubsitute mocking AS/IS .net - c#

I am having hard time mocking IDbConnection. I have a method that returns IDbConnection but than I have a check to verify if this connection is NpgsqlConnection like this:
if (conn as NpgsqlConnection == null)
{
throw new System.Exception("error");
}
and while method returns mock object, casting(as) returns null and creates an exception. How can I use NSubsiute so it will treat it as NpgsqlConnection object?
And second question that is following up, if this one could be resolved is that I am using BeginBinaryImport from NpgsqlConnection which does not have an interface and I cannot mock it, how can I fake it, so it won't throw an error when used like this using var importer = conn.BeginBinaryImport("COPY..... ?

It depends on what you want to test actually. If you want to test the functionality of NpgsqlConnection also, you can create a NpgsqlConnection with a test connection string.
public void DoSomething()
{
// returns NpgsqlConnection with test connection string
// If you substituted for a class rather than an interface, check that the call to your substitute was on a virtual/abstract member.
IDbConnection conn = _connectionManager.GetConnection();
if (conn as NpgsqlConnection == null)
{
throw new System.Exception("error");
}
// functionality
using (var writer = (conn as NpgsqlConnection).BeginBinaryImport("COPY data (field_text, field_int4) FROM STDIN BINARY"))
{
// do some stuff
}
}
Here. You can make _connectionManager.GetConnection(); to return a test db connection which is a NpgsqlConnection. So you can test the code.
You can set it up like this:
var testConnection = new NpgsqlConnection("TESTCONNECTIONSTRING");
var conn = Substitute.For<ConnectionManager>();
conn.GetConnection().Returns(testConnection);
Otherwise, You need a dependency which abstracts functionality away from calling code. You don't need to worry too much about what a dependency is doing.
Your code can be something like this instead:
public void DoSomething()
{
IDbConnection conn = _connectionManager.GetConnection(); // returns NpgsqlConnection
_npgsqlConnectionHelper.ValidateConnection(conn);
_npgsqlConnectionHelper.DoFunctionality(conn);
}
Here, you can mock _npgsqlConnectionHelper

Related

Disposing of a SqlConnection manually in XUnit tests

I am writing SQL Server integration tests using xUnit.
My tests look like this:
[Fact]
public void Test()
{
using (IDbConnection connection = new SqlConnection(_connectionString))
{
connection.Open();
connection.Query(#$"...");
//DO SOMETHING
}
}
Since I am planning to create multiple tests in the same class I was trying to avoid creating a new SqlConnection every time. I know that xUnit framework per se creates an instance of the class per each running test inside it.
This means I could make the creation of the SqlConnection in the constructor since anyway a new one will be created every time a new test run.
The problem is disposing it. Is it good practice or do you see any problem in disposing manually the SqlConnection at the end of each test?
Such as:
public class MyTestClass
{
private const string _connectionString = "...";
private readonly IDbConnection _connection;
public MyTestClass()
{
_connection = new SqlConnection(_connectionString));
}
[Fact]
public void Test()
{
_connection.Open();
_connection.Query(#$"...");
//DO SOMETHING
_connection.Dispose();
}
}
I was trying to avoid creating a new SqlConnection every time.
It's okay to create and dispose a new SqlConnection over and over. The connection instance is disposed, but the underlying connection is pooled. Under the hood it may actually use the same connection repeatedly without closing it, and that's okay.
See SQL Server Connection Pooling.
So if that's your concern, don't worry. What you are doing in the first example is completely harmless. And however your code is structured, if you're creating a new connection when you need it, using it, and disposing it, that's fine. You can do that all day long.
If what concerns you is the repetitive code, I find this helpful. I often have a class like this in my unit tests:
static class SqlExecution
{
public static void ExecuteSql(string sql)
{
using (var connection = new SqlConnection(GetConnectionString()))
{
using (var command = new SqlCommand(sql, connection))
{
connection.Open();
command.ExecuteNonQuery();
}
}
}
public static T ExecuteScalar<T>(string sql)
{
using (var connection = new SqlConnection(GetConnectionString()))
{
using (var command = new SqlCommand(sql, connection))
{
connection.Open();
return (T)command.ExecuteScalar();
}
}
}
public static string GetConnectionString()
{
// This may vary
}
}
How you obtain the connection string may vary, which is why I left that method empty. It might be a configuration file, or it could be hard-coded.
This covers the common scenarios of executing something and retrieving a value, and allows me to keep all the repetitive database code out of my tests. Within the test is just one line:
SqlExecution.ExecuteSql("UPDATE WHATEVER");
You can also use dependency injection with xUnit, so you could write something as an instance class and inject it. But I doubt that it's worth the effort.
If I find myself writing more and more repetitive code then I might add test-specific methods. For example the test class might have a method that executes a certain stored procedure or formats arguments into a query and executes it.
You can also do dependency injection with xUnit so that dependencies are injected into the class like with any other class. There are lots of answers about this. You may find it useful. Maybe it's the reason why you're using xUnit. But something simpler might get the job done.
Someone is bound to say that unit tests shouldn't talk to the database. And they're mostly right. But it doesn't matter. Sometimes we have to do it anyway. Maybe the code we need
to unit test is a stored procedure, and executing it from a unit test and verifying the
results is the simplest way to do that.
Someone else might say that we shouldn't have logic in the database that needs testing, and I agree with them too. But we don't always have that choice. If I have to put logic in SQL I still want to test it, and writing a unit test is usually the easiest way. (We can call it an "integration test" if it makes anyone happy.)
There's a couple different things at play here. First, SqlConnection uses connection pooling so it should be fine to create/dispose the connections within a single test.
Having said that disposing of the connections on a per test class basis would also be doable. XUnit will dispose of test classes that are IDisposable. So either would work. I'd suggest it's cleaner to create/dispose them within the test.
public class MyTestClass : IDisposable
{
const string ConnectionStr = "";
SqlConnection conn;
public MyTestClass()
{
this.conn = new SqlConnection(ConnectionStr);
}
public void Dispose()
{
this.conn?.Dispose();
this.conn = null;
}
public void Test()
{
using (var conn = new SqlConnection(ConnectionStr))
{
}
}
}

What context to use in order to run raw query on simplemembership tables MVC 4 EF6

I'm new to .Net MVC and I wanted to run a raw query on my UserInRoles table.
I think I will need a database context to run it.
I'm unsure what context to use. Can some one recommend me a direction to take? Currently, the ObjectContext does not allow me to instantiate without a connection string. Is directly grabbing the connection string from web config correct?
Error 1 'System.Data.Entity.Core.Objects.ObjectContext' does not contain a constructor that takes 0 arguments
using (var ctx = new ObjectContext())
{
string query = "INSERT INTO dbo.webpages_UsersInRoles (RoleId,UserId) values ("+chk+","+id+");";
ExecuteSql(ctx,query);
}
ExecuteSql is using ADO.net connections different from what EF recommends but I need to do this manual insert in order for this section to work.
static void ExecuteSql(ObjectContext c, string sql)
{
var entityConnection = (System.Data.EntityClient.EntityConnection)c.Connection;
DbConnection conn = entityConnection.StoreConnection;
ConnectionState initialState = conn.State;
try
{
if (initialState != ConnectionState.Open)
conn.Open(); // open connection if not already open
using (DbCommand cmd = conn.CreateCommand())
{
cmd.CommandText = sql;
cmd.ExecuteNonQuery();
}
}
finally
{
if (initialState != ConnectionState.Open)
conn.Close(); // only close connection if not initially open
}
}
The ObjectContext (MSDN Link) requires you to provide a connection string to execute against. The ObjectContext is not your EF container but a context to query against a database and transform to objects. Because it is a generic query mechanism it does not know which connection string to use. In addition, your query is a simple insert query making the ObjectContext the wrong tool for the job. As the ObjectContext provides mapping mechanisms that you will not require I would suggest using your EF container to execute the query. This can be done by calling (sample code)
dbContainer.Database.ExecuteSqlCommand(query)
This command will grab your existing connection string from your configuration file and execute the query provided. Finally there is another option if you really want a ObjectContext without having to enter the connection string. You can do this by providing a wrapper, or static method to create an ObjectContext without the connection string. Such as.
Method 1: Wrapper (inheritance)
class MyObjectContext : ObjectContext
{
public MyObjectContext()
: base(MyObjectContext.connectionString)
{ }
/// <summary>
/// the connection string id in the config
/// </summary>
const string connectionStringID = "dbCon";
/// <summary>
/// gets the connection string
/// </summary>
static string connectionString
{
get
{
return ConfigurationManager.ConnectionStrings[connectionStringID].ConnectionString
}
}
}
Method 2. Static Property (or method)
static ObjectContext New
{
get
{
return new ObjectContext(ConfigurationManager.ConnectionStrings["dbCon"].ConnectionString);
}
}
Now personally I prefer method 1 (if i had to do this) as it also gives me the ability to extend this class to define my queries in one class such as.
class MyObjectContext : ObjectContext
{
//.....
public void Insert_UserInRole(string roleID, string id)
{
///TODO DO: insert role
}
//.....
}
And can be called such as.
using (var context = new MyObjectContext())
{
context.Insert_UserInRole("abc", "123");
}
[Just a thought]
Important In addition your query is begging for SQL Injection. Use "parameters" in your queries. Using parameters will prevent SQL inject atacks. Here is a SO topic regarding parameters. How to pass parameters to the DbContext.Database.ExecuteSqlCommand method?
I hope this helps.

C# web service and static DB Connection

If I crate a static DB Connection into a C# Web service
This instance of connection is shared on all istance of web service? So, In this way could I have problem some this?
Not allowed to change the 'ConnectionString' property while the
connection (state=Connecting)
I get the instance in this way:
public static OleDbConnection GetDatabaseConnection(string aConnectionString)
{
if (_dbConnection == null)
{
_dbConnection = new OleDbConnection(aConnectionString);
_dbConnection.Open();
}
else
{
_dbConnection.Close();
_dbConnection = new OleDbConnection(aConnectionString);
_dbConnection.Open();
}
Log.Logger.log("Aperta connessione al DB");
return _dbConnection;
}
It is always a bad practice to keep a global connection instance. You should follow the standard pattern: create, open, use, close and destroy.
Working against this will result, sooner or later, in problems.
The Connection Pooling mechanism has been studied just for this.
The Pool will help you to avoid this bad habit to keep an object so expensive like a database connection open for unforeseeable time
public static OleDbConnection GetDatabaseConnection(string aConnectionString)
{
OleDbConnection odb = new OleDbConnection(aConnectionString);
odb.Open();
Log.Logger.log("Aperta connessione al DB");
return odb;
}
then your client code use the using statement to close and destroy the connection
using(OleDbConnection cn = SqlClassHelper.GetDatabaseConnection(constring))
{
// define here your OleDbCommand, OleDbDataReader etc...
// use the objects
} // <- here the closing brace close and destroy the connection
Yes, you will have problems with your code in a multithreaded web service.
Your function GetDatabaseConnection works like a factory, everybody who calls it gets a new instance of connection. You do not need static _dbConnection class member, just make it a local variable:
public static OleDbConnection GetDatabaseConnection(string aConnectionString)
{
OleDbConnection _dbConnection = new OleDbConnection(aConnectionString);
_dbConnection.Open();
Log.Logger.log("Aperta connessione al DB");
return _dbConnection;
}

using statements

Today I noticed a snippet of code that looks like the one below:
public class Test
{
SqlConnection connection1 =
new SqlConnection(ConfigurationManager.ConnectionStrings["c1"].ToString());
SqlConnection connection2 =
new SqlConnection(ConfigurationManager.ConnectionStrings["c2"].ToString());
public void Method1()
{
using (connection1)
{
connection1.Open();
using (SqlCommand newSqlCommand = new SqlCommand("text",connection2))
{
// do something
}
}
}
public void Method2()
{
using (connection1)
{
// do something
}
}
}
I am just wondering why would anyone want to open the connection when creating the class and not when calling the corresponding methods inside the class?
EDIT: I should have probably posted the whole code instead. So I do see where they are opening connection1, but then they are instantiating a sqlcommand with a different sql connection (connection2) which has not been opened anywhere. What am I missing here?
Thanks,
This line only initializes a connection object, which can later be used to open a connection to a database server.
SqlConnection connection1 =
new SqlConnection(ConfigurationManager.ConnectionStrings["c1"].ToString());
What I know is that using disposes of an object (and in the case of Connection objects they are automatically closed) after its scope so I wouldn't recommend such usage because it might be problematic with other object types (other than Connection) that can't be used after having their dispose called.
connection1 = new SqlConnection(...) does not really open the connection. It just creates the connection object.
You have to call connection1.Open(); to actually open it. You can do this inside using statement block.
Refer to this MSDN page for more details.
It either
written this way to enforce only single call to a method be performed on the class
unintentionally confusing by throwing ObjectDisposed exception if you call 2 methods
contains connection re-initialization code in blocks you've ommited.
The code is dangerous.
If you call Method1 then Method2 (or visa versa) you will get an error (connection string not initialized).
The error occurs because the using statement will close the connection AND Disposes the object. I double checked what happens when dispose is called...the connection string is cleared (and possibly some other things I didn't notice).
You don't want to re-use a disposed object.
The cost of instantiating a new connection object is insignificant so I would just create the object where needed, maybe with a little factory method to reduce code duplication, so change to something like:-
private static SqlConnection GetSqlConnection()
{
return new SqlConnection(ConfigurationManager.ConnectionStrings["c1"].ToString());
}
private void Method1()
{
using (var conn = GetSqlConnection())
{
conn.Open();
// do stuff...
}
}
private void Method2()
{
using (var conn = GetSqlConnection())
{
conn.Open();
// do other stuff...
}
}
Of course there are many different ways of approaching this problem, this is just one and indeed quite a simplistic one...but it is a good starting point and is safe :-)

Is Mocking able to replace functionality wrapped inside a method?

I'm trying to define a way to simulate an case on accessing into a database without accessing... That's probably sounds quite crazy, but it's not.
Here is an example about a method i would like to test:
public IDevice GetDeviceFromRepository(string name)
{
IDevice device = null;
IDbConnection connection = new SqlConnection(ConnectionString);
connection.Open();
try
{
IDbCommand command = connection.CreateCommand();
command.CommandText = string.Format("SELECT DEVICE_ID,DEVICE_NAME FROM DEVICE WHERE DEVICE_NAME='{0}'", name);
IDataReader dataReader = command.ExecuteReader();
if(dataReader.NextResult())
{
device = new Device(dataReader.GetInt32(0),dataReader.GetString(1));
}
}
finally
{
connection.Close();
}
return device;
}
I'm pretending to mock IDataReader so i can control what's being read. Something like that (using Moq framework):
[TestMethod()]
public void GetDeviceFromRepositoryTest()
{
Mock<IDataReader> dataReaderMock = new Mock<IDataReader>();
dataReaderMock.Setup(x => x.NextResult()).Returns(true);
dataReaderMock.Setup(x => x.GetInt32(0)).Returns(000);
dataReaderMock.Setup(x => x.GetString(1)).Returns("myName");
Mock<IDbCommand> commandMock = new Mock<IDbCommand>();
commandMock.Setup(x => x.ExecuteReader()).Returns(dataReaderMock.Object);
Mock<RemoveDeviceManager> removeMock = new Mock<RemoveDeviceManager>();
removeMock.Setup()
RemoveDeviceManager target =new RemoveDeviceManager(new Device(000, "myName"));
string name = string.Empty;
IDevice expected = new Device(000, "myName"); // TODO: Initialize to an appropriate value
IDevice actual;
actual = target.GetDeviceFromRepository(name);
Assert.AreEqual(expected.SerialNumber, actual.SerialNumber);
Assert.AreEqual(expected.Name, actual.Name);
}
My question is whether i can force method GetDeviceFromRepository to replace IDataReader by mocked one.
Although you're currently use Moq I think that the functionality you're looking for cannot be achived without dependency injection unless you use Typemock Isolator (Disclaimer - I worked at Typemock).
Isolator has a feature called "future objects" that enable replacing a future instantiation of an object with a previously created fake object:
// Create fake (stub/mock whateever) objects
var fakeSqlConnection = Isolate.Fake.Instance<SqlConnection>();
var fakeCommand = Isolate.Fake.Instance<SqlCommand>();
Isolate.WhenCalled(() => fakeSqlConnection.CreateCommand()).WillReturn(fakeCommand);
var fakeReader = Isolate.Fake.Instance<SqlDataReader>();
Isolate.WhenCalled(() => fakeCommand.ExecuteReader()).WillReturn(fakeReader);
// Next time SQLConnection is instantiated replace with our fake
Isolate.Swap.NextInstance<SqlConnection>().With(fakeSqlConnection);
I would think the problem here is your direct dependency ultimately to SqlConnection. If you would use some variant of dependency injection such that your code gets access to the IDbCommand without knowing how it gets constructed, you would be able to inject your mock without much of a hassle.
I understand this doesn't quite answer your question, but in the long run doing stuff as described will give you far better testability.
I agree with Frank's answer that moving toward Dependency Injection is the better long-term solution, but there are some intermediate steps you can take to move you in that direction without biting the whole thing off.
One thing is to move the construction of the IDbConnection class into a protected virtual method inside your class:
protected virtual IDbConnection CreateConnection()
{
return new SqlConnection(ConnectionString);
}
Then, you can create a testing version of your class like so:
public class TestingRemoteDeviceManager : RemoteDeviceManager
{
public override IDbConnection CreateConnection()
{
IDbConnection conn = new Mock<IDbConnection>();
//mock out the rest of the interface, as well as the IDbCommand and
//IDataReader interfaces
return conn;
}
}
That returns a Mock or fake IDbConnection instead of the concrete SqlConnection. That fake can then return a fake IDbCommand object, which can then return a fake IDataReader object.
The mantra is test until fear is transformed in boredom. I think you've crossed that line here. If you would take control of the data reader, then the only code you're testing is this:
device = new Device(dataReader.GetInt32(0),dataReader.GetString(1));
There is almost nothing to test here, which is good: the data layer should be simple and stupid. So don't try to unit test your data layer. If you feel you must test it, then integration-test it against a real database.
Of course, hiding your data layer behind a IDeviceRepository interface so that you can easily mock it in order to test other code is still a good idea.

Categories