2016-09-08 3 views
2

Я хочу, чтобы проверить свою обработку в MongoWriteException с помощью драйвера Монго, вот выборочный метод:Модульное тестирование 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; 
      } 
     } 
    } 

Кто-нибудь знает, как я могу издеваться в MongoWriteException? Я пытался построить его так:

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

Но класс WriteError имеет внутренний конструктор

+0

Я не так хорошо знаком с монгодбом. какой тип '_documentStore'. Я думаю, вам, возможно, потребуется отвлечь вас от доступа к драйверу, это еще не все. – Nkosi

+0

Магазин документов - это просто фасад. Реальная проблема заключается в том, что я не могу имитировать происходящее исключение. –

+0

Где это обычно происходит. может быть, вы можете использовать moq, чтобы бросить его, когда вы называете одного из насмешек. – Nkosi

ответ

3

Небольшой пример, основанный на the driver's own tests, но с помощью отражения, чтобы добраться до внутренних конструкторов

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

Существует также конструктор с помощью SerializationInfo, который может иметь подобный запах.

0

Вы можете создать объект класса с внутренней конструктор с помощью отражения.

Что-то вроде

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

Второй параметр в приведенном выше коде, чтобы указать Активатор искать, не являющихся конструкторами общественного умолчанию.

Но таким образом вы не можете инициализировать какие-либо значения или использовать конструкторы с параметрами.

Я предполагаю, что вы создали фальшивую сборку для библиотеки библиотеки mogo и с помощью прокладки, чтобы высмеять метод UpdateOne.

Если это возможно, вы можете перетащить объект WriteError и сделать свойство «Категория» возвратить любое значение, которое вы желаете в соответствии с тестовым случаем.

Было бы что-то вроде

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

Синтаксис может отличаться в приведенном выше коде. но идея такая же.

0

Итак, я принял ответ @logan rakai здесь (https://stackoverflow.com/a/39497316/1001408) и немного изменил его. Вот что я закончил.

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

 Смежные вопросы

  • Нет связанных вопросов^_^