Search code examples
c#mongodbnunitmoqmongodb-.net-driver

Unit testing MongoWriteExceptions


I want to test my handling of a MongoWriteException using the Mongo driver, here is a sample method:

    private void Update()
    {
        try
        {
            var find = Builders<Filter>.Filter.Eq(e => e.Id, "someId");
            var update = Builders<Filter>.Update.Set(e => e.SomeValue, "AValue");
            _documentStore.MongoCollection<Filter>().UpdateOne(find, update, new UpdateOptions { IsUpsert = true }, CancellationToken.None);
        }
        catch (MongoWriteException mongoWriteException)
        {
            if (mongoWriteException.WriteError.Category != ServerErrorCategory.DuplicateKey)
            {
                throw;
            }
        }
    }

Does anyone know how I can mock a MongoWriteException? I tried to construct it like so:

var mongoWriteException = new MongoWriteException(new ConnectionId(new ServerId(new ClusterId(1), new DnsEndPoint("d", 2)), 0), new WriteError(), // <- Protected constructor

But the WriteError class has an internal constructor


Solution

  • A small example based on the driver's own tests but using reflection to get to the internal constructors

    static class MockMongoCollection // : IMongoCollection<TDocument>
    {
        private static readonly MongoWriteException __writeException;
    
        static MockMongoCollection()
        {
            var connectionId = new ConnectionId(new ServerId(new ClusterId(1), new DnsEndPoint("localhost", 27017)), 2);
            var innerException = new Exception("inner");
            var ctor = typeof (WriteConcernError).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)[0];
            var writeConcernError = (WriteConcernError)ctor.Invoke(new object[] { 1, "writeConcernError", new BsonDocument("details", "writeConcernError") });
            ctor = typeof (WriteError).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)[0];
            var writeError = (WriteError) ctor.Invoke(new object[] {ServerErrorCategory.Uncategorized, 1, "writeError", new BsonDocument("details", "writeError")});
            __writeException = new MongoWriteException(connectionId, writeError, writeConcernError, innerException);
        }
    
        public static void UpdateOne()
        {
            throw __writeException;
        }
    }
    
    class ExampleTests
    {
        [Test]
        public void UncategorizedWriteExceptionTest()
        {
            Assert.Throws<MongoWriteException>(MockMongoCollection.UpdateOne);
        }
    }
    

    There is also a constructor using SerializationInfo which may have a similar smell.