bchavez / RethinkDb.Driver

:headphones: A NoSQL C#/.NET RethinkDB database driver with 100% ReQL API coverage.
http://rethinkdb.com/api/java
Other
384 stars 134 forks source link

Unit testing and Mocking IConnection #109

Closed oliverjanik closed 7 years ago

oliverjanik commented 7 years ago

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?

bchavez commented 7 years ago

Hi Oliver, hope you're doing well.

I don't think it's a good idea to open them up for the following reasons:

  1. It will pollute the ReQL API with unnecessary TermType, Args, OptArgs.
  2. 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.
  3. 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")
  4. 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! :+1:

Thanks, Brian

:beach_umbrella: :trumpet: Beach Boys - Good Vibrations (Nick Warren bootleg)

oliverjanik commented 7 years ago

Hmm, the string comparison will work for me I think.