Trouble mocking SqlConnection for Unit Tests - c#

I am calling code that I cannot change that takes in a SqlConnection and a Transaction created from that SqlConnection. I am attempting to mock this SqlConnection using Moq 4.16.1. I am getting the following error when attempting to unit test the code:
Unable to cast object of type 'Castle.Proxies.IDbConnectionProxy' to type 'System.Data.SqlClient.SqlConnection'.
I have wrapped the SqlConnection in my own wrapper to try to get this to work, but this has not helped.
SqlConnectionWrapper:
using System.Data;
using System.Data.SqlClient;
namespace Wrappers
{
public class SQLConnectionWrapper : ISQLConnectionWrapper
{
public string ConnectionString { get; private set; }
public SQLConnectionWrapper(string connectionString)
{
ConnectionString = connectionString;
}
public IDbConnection Open()
{
return new SqlConnection(ConnectionString);
}
}
}
Unit test:
private Mock<ISQLConnectionWrapper> _mockSqlConnectionWrapper;
[SetUp]
public void Setup()
{
_mockSqlConnectionWrapper = new Mock<ISQLConnectionWrapper>();
var mockSQLConnection = new Mock<IDbConnection>();
mockSQLConnection.SetupAllProperties();
_mockSqlConnectionWrapper.Setup(x => x.Open())
.Returns(mockSQLConnection.Object);
}
Any help with this would be greatly appreciated.

Related

How to access static methode when its in class

Here I write some code in static methode which is in class file please Help me how can i create instance of static class
public class ConnectionString
{
public static void CreateCommand(string querystring, string connectionString)
{
using(SqlConnection cn = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand(querystring, cn);
cmd.Connection.Open();
cmd.ExecuteNonQuery();
}
}
}
Just call it like this:
string querystring = "Your values here";
string connectionString = "Your values here";
ConnectionString.CreateCommand(querystring, connectionString);
That's it.
Your ConnectionString class can be refactored to implement an interface like this:
public interface IDataAccess
{
void CreateCommand(string querystring, string connectionString);
}
this interface allows us to inject its implementation in the controller that you mentioned in the comments. So your ConnectionString class (renamed to more meaningful name DataAccess) should look like this:
public class DataAccess : IDataAccess
{
public void CreateCommand(string querystring, string connectionString)
{
using (SqlConnection cn = new SqlConnection(connectionString))
{
cn.Open();
using (SqlCommand cmd = new SqlCommand(querystring, cn))
{
cmd.ExecuteNonQuery();
}
}
}
}
then in your controller / client class you can have the concrete implementation injected at the run time..
public class DataController : Controller
{
private readonly IDataAccess dataAccess;
public DataController(IDataAccess dataAcces)
{
this.dataAccess = dataAcces;
}
public ActionResult ShowData()
{
string querystring = "you t-sql query";
string connectionString = "<you sql connection string>";
this.dataAccess.CreateCommand(querystring, connectionString);
return this.View();
}
}
If you are using MVC and dont know how to resolve the dependencies then refer to this article
Alternatively you can just new up the instance of DataAccess class like this:
public class DataController : Controller
{
private readonly IDataAccess dataAccess;
public DataController()
{
this.dataAccess = new DataAccess();
}
public ActionResult ShowData()
{
string querystring = "you t-sql query";
string connectionString = "<you sql connection string>";
this.dataAccess.CreateCommand(querystring, connectionString);
return this.View();
}
}
I will not recommend this approach as it wont be possible to unit test it.
Hope this helps!

Strange behavior creating a new Database with Npgsql and Entity Framework

I'm trying to create a new database with npgsql and EF 6. This is my code:
using System.Data.Common;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Migrations;
using System.Data.Entity;
using System.Data.Entity.Migrations.Sql;
using Npgsql;
using NUnit.Framework;
namespace EntityFramework.PostgreSql.Test.IntegrationTests
{
[TestFixture]
public class PostgreSqlMigrationSqlGeneretorHistoryTest
{
private const string ConnectionString = "Server=127.0.0.1;Port=5432;Database=testEF6;User Id=postgres;Password=p0o9i8u7y6;CommandTimeout=20;Preload Reader = true;";
private const string ProviderName = "Npgsql";
[Test]
public void CreateNewDatabase()
{
const string cs = "Server=127.0.0.1;Port=5432;Database=testEFxx;User Id=postgres;Password=p0o9i8u7y6;CommandTimeout=20;Preload Reader = true;";
var db = new LocalPgContext(cs);
if (!db.Database.Exists())
db.Database.Create();
var exists = db.Database.Exists();
db.Database.Delete();
Assert.IsTrue(exists);
}
public class LocalPgContext : DbContext, IDbProviderFactoryResolver, IDbConnectionFactory
{
public LocalPgContext(string nameOrConnectionString) : base(nameOrConnectionString)
{
Database.SetInitializer(new CreateDatabaseIfNotExists<LocalPgContext>());
}
public DbProviderFactory ResolveProviderFactory(DbConnection connection)
{
return DbProviderFactories.GetFactory("Npgsql");
}
public DbConnection CreateConnection(string nameOrConnectionString)
{
return new NpgsqlConnection(nameOrConnectionString);
}
DbConnection IDbConnectionFactory.CreateConnection(string nameOrConnectionString)
{
return CreateConnection(nameOrConnectionString);
}
DbProviderFactory IDbProviderFactoryResolver.ResolveProviderFactory(DbConnection connection)
{
return new LocalPgProviderFactory();
}
}
public class LocalPgProviderFactory : DbProviderFactory
{
public override DbConnectionStringBuilder CreateConnectionStringBuilder()
{
return new NpgsqlConnectionStringBuilder(ConnectionString);
}
public override DbConnection CreateConnection()
{
return new NpgsqlConnection(ConnectionString);
}
}
}
}
The strange thing is that I create a new connection using Npgsql but when I'm executing if (!db.Database.Exists()) it try to create a connection using SqlServer provider. It tell me that it doesn't know the "port" attribute of the connection string because sql server haven't this attribute.
I'm thinking that it is looking for the default provider factory into the web.config file but not finding it, it set sql server as default provider.
I would like to set Npgsql as default provider without using a config file at all.
Npgsql add the support to delete or create the database from the 2.2.0 version (now is in beta 1)

why isn't TestInitialize getting called automatically?

I'm using Microsoft.VisualStudio.TestTools.UnitTesting; but the method I marked as [TestInitialize] isn't getting called before the test. I've never used this particular testing framework before but in every other framework there is always a way of registering a Setup and TearDown method that will auto run before and after every single test. Is this not the case with the visual studio testing tools unit testing framework?
[TestClass]
public class RepoTest
{
private const string TestConnectionString = #"Server=localhost\SQL2014EXPRESS64; Database=RepoTest; Trusted_Connection=True;";
private const string MasterConnectionString = #"Server=localhost\SQL2014EXPRESS64; Database=master; Trusted_Connection=True;";
[TestInitialize]
private void Initialize()
{
using(var connection = new SqlConnection(MasterConnectionString))
using(var command = new SqlCommand(Resources.Initialize, connection))
{
command.ExecuteNonQuery();
}
}
[TestCleanup]
private void Cleanup()
{
using (var connection = new SqlConnection(MasterConnectionString))
using (var command = new SqlCommand(Resources.Cleanup, connection))
{
command.ExecuteNonQuery();
}
}
[TestMethod]
public void CreateARepo()
{
var repo = new Repo(TestConnectionString);
}
}
Make Initialize and Cleanup public. You can also check, that at msdn all examples have public accessor.
In order to reproduce, make such test class:
[TestClass]
public class Tests
{
[TestInitialize]
public void Initialize()
{
Console.WriteLine("initialize");
}
[TestCleanup]
public void Cleanup()
{
Console.WriteLine("cleanup");
}
[TestMethod]
public void Test()
{
Console.WriteLine("test body");
}
}
That test will produce the following results:
Making Initialize and Cleanup private, you'll see only test body being printed to the console:
Used Microsoft.VisualStudio.QualityTools.UnitTestFramework assembly as unit testing framework version 10.1.0.0 and ReSharper 8.2 as a test runner.

Connecting to a SQL server using ADODB from a C# dll

I am writing a custom Connection class in C# for Excel to be able to connect to a SQL Server.
When I use SQLConnection from System.Data.SqlClient library I am able to establish a connection. The working code I've got:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlClient;
using System.Runtime.InteropServices;
namespace Test
{
[InterfaceType(ComInterfaceType.InterfaceIsDual),
Guid("6E8B9F68-FB6C-422F-9619-3BA6D5C24E84")]
public interface IConnection
{
bool Status { get; }
bool Open();
}
[ClassInterface(ClassInterfaceType.None)]
[Guid("B280EAA4-CE11-43AD-BACD-723783BB3CF2")]
[ProgId("Test.Connection")]
public class Connection : IConnection
{
private bool status;
private SqlConnection conn;
private string connString = "Data Source=[server]; Initial Catalog=[initial]; User ID=[username]; Password=[password]";
public Connection()
{
}
public bool Status
{
get
{
return status;
}
}
public bool Open()
{
try
{
conn = new SqlConnection(connString);
conn.Open();
status = true;
return true;
}
catch(Exception e)
{
e.ToString();
return false;
}
}
}
}
And after adding the reference to Excel I am able to test the connection using a simple VBA code like this:
Sub TestConnection()
Dim conn As Test.Connection
Set conn = New Test.Connection
Debug.Print conn.Status
conn.Open
Debug.Print conn.Status
End Sub
It outputs:
False
True
So everything is fine. Now I would like to create custom Recordset class in my C# library so I decided to use an ADODB library and its RecordSetinstead of SqlDataReader as I am planning to work with some big chunks of data. So, I have modified my code to this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlClient;
using System.Runtime.InteropServices;
namespace Test
{
[InterfaceType(ComInterfaceType.InterfaceIsDual),
Guid("6E8B9F68-FB6C-422F-9619-3BA6D5C24E84")]
public interface IConnection
{
bool Status { get; }
bool Open();
}
[ClassInterface(ClassInterfaceType.None)]
[Guid("B280EAA4-CE11-43AD-BACD-723783BB3CF2")]
[ProgId("Test.Connection")]
public class Connection : IConnection
{
private bool status;
private ADODB.Connection conn = new ADODB.Connection();
private string connString = "Data Source=[server]; Initial Catalog=[initial]; User ID=[username]; Password=[password]";
public Connection()
{
}
public bool Status
{
get
{
return status;
}
}
public bool Open()
{
try
{
conn.ConnectionString = connString;
conn.Open();
// conn.Open(connString, ["username"], ["password"], 0)
// what else can I try? is this where it actually fails?
status = true;
return true;
}
catch (Exception e)
{
e.ToString();
return false;
}
}
}
}
I also have added references to Microsoft ActiveX Data Objects 6.1 Library.
Now, when I am executing the VBA code it outputs:
0
0
But I was expecting 0 and 1. It seems to me like I am not properly connecting to the server ( credentials are the same i have just removed actual data from this code ).
I have tried to use different variations of the connection string, however it always returns 0 and 0. I have tried creating a new project with new GUIDs and also tried renaming the projects, classes, etc. nothing has worked. I am suspecting its the establishment of the connection but I am unsure how to debug a dll.
I have used link1, link2, link3, link4 for reference
Update:
I have wrote the exception to the file as TheKingDave suggested. This is the exception error message
System.Runtime.InteropServices.COMException (0x80004005):
[Microsoft][ODBC Driver Manager] Data source name not found and no
default driver specified at ADODB._Connection.Open(String
ConnectionString, String UserID, String Password, Int32 Options) at
TestADODB.Connection.Open() in c:\Users\administrator\Documents\Visual
Studio 2012\Projects\Test\Test\Connection.cs:line 49
The connection string is missing Provider=SQLOLEDB.
The ADODB.Connection needs to know what type of database it is connecting to.

Mocking data access Layer Rhino mock

How can i mock data access layer using Rhino mocks
I have the following classes:
public interface IDataAccess
{
int ExecuteNoneQuery(SqlConnection connection, string storedProcedureName,
IEnumerable<SqlParameter> sqlParameters);
}
public class DataAccess : IDataAccess
{
public int ExecuteNoneQuery(SqlConnection connection, string storedProcedureName,
IEnumerable<SqlParameter> sqlParameters)
{
using (SqlCommand command = connection.CreateCommand())
{
// do some stuff
return command.ExecuteNonQuery();
}
}
}
public class DbOperation<T>
{
private IDataAccess _access;
public DbOperation(IDataAccess access)
{
_access = access;
}
public int Insert(T item, SqlConnection connection,string spName)
{
IDbObjectFactory<T> parametersFactory = new SqlParameterFactory<T>();
var parameters = (IList<SqlParameter>)parametersFactory.GetDbObject(item);
return _access.ExecuteNoneQuery(connection, spName, parameters);
}
}
Here is an example with some explanations:
To test the case:
WHEN method ExecuteNoneQuery of class DataAccess is called
THEN command.ExecuteNonQuery() should be called:
// 1. Create `SqlCommand` Mock:
var command = MockRepository.GenerateMock<SqlCommand>();
// 2. Create `SqlConnection` Stub:
var connection = MockRepository.GenerateStub<SqlConnection>();
// 3. Setup connection.CreateCommand() to return mocked command:
connection
.Stub(c => c.CreateCommand())
.Return(command);
// 4. Do test action:
var dataAccess = new DataAccess();
dataAccess.ExecuteNoneQuery(connection, null, null);
// Assert command.ExecuteNonQuery() has been called:
command.AssertWasCalled(c => c.ExecuteNonQuery());
Hope that explains a bit how to use Rhino Mock.
I assume you want to test DbOperation by mocking DataAccess.
public void TestInsert()
{
var dataAccess = MockRepository.GenerateMock<IDataAccess>();
var dbOperation = new DbOperation<string>(dataAccess);
var sqlConnection = new SqlConnection();
dbOperation.Insert("blah", sqlConnection, "MySP");
dataAccess.AssertWasCalled(a => a.ExecuteNoneQuery(
Arg.Is(sqlConnection),
Arg.Is("MySP"),
Arg<IEnumerable<SqlParameter>>.Is.Anything));
}
Ideally, you may want to even inject IDbObjectFactory<T> so that you can test the interaction between DbOperation and the sqlParameterFactory - and hence you could also check that ExecuteNoneQuery was called with the exact parameters that sqlParameterFactory would return.

Categories