2016-09-08 5 views
2

ich meine Handhabung eines MongoWriteException testen wollen den Mongo-Treiber, hier ist ein Beispiel Methode:Unit-Tests MongoWriteExceptions

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; 
      } 
     } 
    } 

Wer weiß, wie ich einen MongoWriteException verspotten? Ich habe versucht, es wie so zu konstruieren:

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

Aber die Writeerror-Klasse verfügt über einen internen Konstruktor

+0

Ich bin nicht so vertraut mit Mongodb. welcher Typ ist '_documentStore'. Ich denke, dass Sie den Zugang zum Treiber abstrahieren müssen, ist es nicht schon. – Nkosi

+0

Document Store ist nur eine Fassade. Das eigentliche Problem ist, dass ich die auftretende Ausnahme nicht simulieren kann. –

+0

Wo würde es normalerweise auftreten. vielleicht kannst du moq benutzen, um es zu werfen, wenn du einen der Mocks anrufst. – Nkosi

Antwort

3

Ein kleines Beispiel basierend auf the driver's own tests jedoch unter Verwendung von Reflexion auf die internen Konstrukteure zu bekommen

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); 
    } 
} 

Es gibt auch einen Konstruktor SerializationInfo verwendet, die einen ähnlichen Geruch aufweisen.

0

Sie erstellen können das Objekt einer Klasse mit Interne Konstruktor Reflexion.

So etwas wie

var obj = Activator.CreateInstance(typeof(WriteError), true); 

Der zweite Parameter in dem obigen Code ist, den Activator angeben, für nicht öffentliche Standardkonstruktoren zu suchen.

Aber auf diese Weise können Sie keine Werte initialisieren oder parametrisierte Konstruktoren verwenden.

Ich nehme an, Sie haben eine falsche Assembly für mogo DB-Bibliothek erstellt und Shim verwendet, um die UpdateOne-Methode zu verspotten.

Wenn dies der Fall ist, können Sie das WriteError-Objekt shimieren und die Eigenschaft "Category" entsprechend dem Testfall einen beliebigen Wert zurückgeben lassen.

Es wäre so etwas wie

ShimsWriteError.AllInstances.Category = errorObj => ServerErrorCategory.DuplicateKey 

werden, um die Syntax in dem obigen Code unterschiedlich sein kann. aber die Idee ist dieselbe.

0

Also nahm ich @logan Rakiis Antwort hier (https://stackoverflow.com/a/39497316/1001408) und änderte es ein wenig. Hier ist, womit ich endete.

[Test] 
    public void GivenADuplicateKeyWriteErrorOccurs_WhenCallingUpdateOne_ThenNoExceptionIsThrown() 
    { 
     // Given 
     var someMongoService = CreateSomeObject(); 

     _mockMongoCollection.Setup(x => x.UpdateOne(It.IsAny<FilterDefinition<SomeObject>>(), It.IsAny<UpdateDefinition<SomeObject>>(), It.IsAny<UpdateOptions>(), default(CancellationToken))).Throws(CreateMongoWriteException(ServerErrorCategory.DuplicateKey)); 

     // When/Then 
     Assert.DoesNotThrow(() => someMongoService.Upsert(new CreateNewSomeObject()); 
    } 

    [Test] 
    public void GivenAExceptionOccursWhichIsNotADuplicateKeyWriteError_WhenCallingUpdateOne_ThenTheExceptionIsThrown() 
    { 
     // Given 
     var someMongoService = CreateFilterService(); 

     var exception = CreateMongoWriteException(ServerErrorCategory.ExecutionTimeout); 
     _mockMongoCollection.Setup(x => x.UpdateOne(It.IsAny<FilterDefinition<SomeObject>>(), It.IsAny<UpdateDefinition<SomeObject>>(), It.IsAny<UpdateOptions>(), default(CancellationToken))).Throws(exception); 

     // When/Then 
     Assert.Throws<MongoWriteException>(() => someMongoService.Upsert(new CreateNewSomeObject()); 
    } 

    public static MongoWriteException CreateMongoWriteException(ServerErrorCategory serverErrorCategory) 
    { 
     var connectionId = new ConnectionId(new ServerId(new ClusterId(1), new DnsEndPoint("localhost", 27017)), 2); 

     var writeConcernError = CreateWriteConcernError(); 
     var writeError = CreateWriteError(serverErrorCategory); 
     return new MongoWriteException(connectionId, writeError, writeConcernError, new Exception()); 
    } 

    private static WriteError CreateWriteError(ServerErrorCategory serverErrorCategory) 
    { 
     var ctor = typeof (WriteError).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)[0]; 
     var writeError = (WriteError)ctor.Invoke(new object[] {serverErrorCategory, 1, "writeError", new BsonDocument("details", "writeError")}); 
     return writeError; 
    } 

    private static WriteConcernError CreateWriteConcernError() 
    { 
     var ctor = typeof(WriteConcernError).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)[0]; 
     return (WriteConcernError)ctor.Invoke(new object[] { 1, "writeConcernError", new BsonDocument("details", "writeConcernError") }); 
    } 
Verwandte Themen