Unit testing and Mocking IConnection
oliverjanik opened this issue · 2 comments
I'm setting up some unit tests that make sure I'm assembling the queries to the DB correctly.
For that purpose I've set up a mock for IConnection, which can intercept calls to conn.Run* methods.
Here's an example:
A.CallTo(() => conn.RunAtomAsync<Result>(A<ReqlAst>.That.Matches(a => ...), A<object>._, A<CancellationToken>._)).MustHaveHappened();
I was about to test the ReqlAst where the ... is in the above examples but I can't access TermType, Arguments or OptArgs. They're all protected internal?
Any change you can make them public or otherwise accessible to tests?
Hi Oliver, hope you're doing well.
I don't think it's a good idea to open them up for the following reasons:
- It will pollute the ReQL API with unnecessary
TermType
,Args
,OptArgs
. - It can mislead users into improperly using these properties. The driver expects these properties to be constructed in a particular way. Users need to be following the public API for opt args etc.
- Determining query equality is difficult this way. You'd have to walk the entire AST (and child terms) to determine if a query is really equal (or a match) to another.
e.g.R.Db("test").Table("foo") != R.Db("test").Table("foo")
- There's a better way...
What you are looking to do can be achieved in an alternative way using query.ToRawString
. Using the query serialization feature solves all the problems outlined above.
[Test]
public async Task can_test_using_mock()
{
var expectedQuery = R.Db(DbName).Table(TableName).ToRawString();
var testQuery = R.Db(DbName).Table(TableName);
var conn = A.Fake<IConnection>();
await testQuery.RunAtomAsync<Result>(conn);
A.CallTo(() =>
conn.RunAtomAsync<Result>(
A<ReqlAst>.That.Matches(test =>
ReqlRaw.ToRawString(test) == expectedQuery),
A<object>._,
A<CancellationToken>._))
.MustHaveHappened();
}
Hope that helps! 👍
Thanks,
Brian
Hmm, the string comparison will work for me I think.