Mocking The Driver for Testing Purposes

185 views
Skip to first unread message

Rob Emery

unread,
Sep 3, 2015, 5:37:32 AM9/3/15
to DataStax C# Driver for Apache Cassandra User Mailing List
Hello,

Just been attempting to wrap some of our Cassandra persistence stuff with tests; and I have a problem getting this mocked out; 
I've created a microcosm of the problem:

public class ConcreteCassandraThing
    {
        private PreparedStatement preparedStatement;
        private ISession cassandraSession;
        private const string CQL = "SELECT column FROM table";
        public ConcreteCassandraThing(ISession cassSession)
        {
            cassandraSession = cassSession;

            preparedStatement = cassandraSession.Prepare(CQL);
            preparedStatement.SetConsistencyLevel(ConsistencyLevel.LocalQuorum);
        }

        public List<string> dostuff()
        {
            var returnValue = new List<string>();
            var bound = preparedStatement.Bind();
            var result = cassandraSession.Execute(bound);
            foreach(var row in result.GetRows())
            {
                returnValue.Add(row.GetValue<string>("column"));
            }
            return returnValue;
        }
    }

    [TestFixture]
    public class CassandraUnmockableProblem
    {
        [Test]
        public void Name()
        {
            var mockCassandra = new Mock<ISession>();
            mockCassandra.Setup(x => x.Prepare(It.IsAny<string>())).Returns(() => new Mock<PreparedStatement>().Object);
            var subject = new ConcreteCassandraThing(mockCassandra.Object);
            subject.dostuff();
        }
    }

Essentially; whilst I can mock out (we're using moq) the CassandraSession; I can't inject setup for the Prepare method as it needs to return a PreparedStatement, which has an internal constructor.

I think it would make sense for the .Prepare to return an IPreparedStatement instead, that way I can inject moq objects at each layer? I'm guessing the same is also true of Row, RowSet; unless (I'm hoping) I've missed something!

Many Thanks
-Rob

Jorge Bay Gondra

unread,
Sep 3, 2015, 6:03:09 AM9/3/15
to csharp-dr...@lists.datastax.com
Hi Rob,
I agree, it would be better to have all methods to return interfaces instead of concrete classes but it was done a long time ago and doing it now would introduce a breaking change for our users.

An intermediate solution would be to introduce a public constructor for PrepareStatement and make Bind() a virtual method. That is the way we solve it for Row and RowSet, what do you think?

Thanks,
Jorge




Phone: 0800 021 0888   Email: cont...@codeweavers.net
Codeweavers Ltd | Barn 4 | Dunston Business Village | Dunston | ST18 9AB
Registered in England and Wales No. 04092394 | VAT registration no. 974 9705 63 

      

To unsubscribe from this group and stop receiving emails from it, send an email to csharp-driver-u...@lists.datastax.com.

Robert Emery

unread,
Sep 3, 2015, 6:09:00 AM9/3/15
to csharp-dr...@lists.datastax.com
Hi Jorge,

Yeah that sounds like an acceptable workaround, do you know if there's a plan for interfaces to be introduced at some point on a major (presumably potentially breaking) upgrade?

Thanks,
--
Robert Emery
Head of Infrastructure

E: rober...@codeweavers.net | T: 01785 711633 | W: www.codeweavers.net

Codeweavers Ltd | Barn 4 | Dunston Business Village | Dunston | ST18 9AB
Registered in England and Wales No. 04092394 | VAT registration no. 974 9705 63 

      

Jorge Bay Gondra

unread,
Sep 3, 2015, 6:15:26 AM9/3/15
to csharp-dr...@lists.datastax.com
I created a ticket for the workaround: CSHARP-337.

About introducing API changes to make all methods return interfaces, its a possibility, we can discuss that.
Reply all
Reply to author
Forward
0 new messages