views:

99

answers:

1

My unit test keeps getting the following error: "System.InvalidOperationException: The Connection is not open."

The Test

[TestFixture]
public class Test
{
   [Test]
    public void Test1()
    {
        NpgsqlConnection connection = MockRepository.GenerateStub<NpgsqlConnection>();

        // Tried to fake the open connection
        connection.Stub(x => x.State).Return(ConnectionState.Open);
        connection.Stub(x => x.FullState).Return(ConnectionState.Open);

        DbQueries queries = new DbQueries(connection);

        bool procedure = queries.ExecutePreProcedure("201003");

        Assert.IsTrue(procedure);
    }
}

Code Under Test

using System.Data;
using Npgsql;

public class DbQueries
{
    private readonly NpgsqlConnection _connection;

    public DbQueries(NpgsqlConnection connection)
    {
        _connection = connection;
    }

    public bool ExecutePreProcedure(string date)
    {
        var command = new NpgsqlCommand("name_of_procedure", _connection);
        command.CommandType = CommandType.StoredProcedure;

        NpgsqlParameter parameter = new NpgsqlParameter {DbType = DbType.String, Value = date};

        command.Parameters.Add(parameter);
        command.ExecuteScalar();

        return true;
    }
 }

How would you test the code using Rhino Mocks 3.6?

PS. NpgsqlConnection is a connection to a PostgreSQL server.

+1  A: 

Hi,

There are a few issues with your approach:

  1. NpgsqlConnection is a class, and my guess is that the state properties are not virtual - so the stub you created is just not going to work (as you noticed0. I don't think there is any workaround.
  2. In your test you are really testing the internals of NpgsqlCommand (because you create a concrete implementation in ExecuteProcedure method). This is a third party class and you should only assume anything about its documented interface, and not the implementation details (e.g. that it uses State property on connection)

So my approach would be to not run any unit tests for this class, because its effectively just a wrapper around a 3rd party library. Go for integration tests instead (so create a test database and connect to it).

Grzenio
Thank you for your comment Grzenio.Your explanation makes sense and clears things up for me why I test was not working.To follow the TDD technique - write test first and then the code, before to write any test:1. Make sure unit testing is valid in the context (ie. you are not testing internals of a third party class);2. In case of 3rd party class, skip unit tests and go ahead with integration test.3. Any already written method containing untestable 3rd party code, should be refactored out into separate method.Is this common practise for TDD?
J Pollack