2016-09-08 4 views
2

は、ここではサンプルの方法である:ユニットテスト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

私はそれほどmongodbに精通していません。どのタイプが '_documentStore'です。私はあなたがドライバにアクセスすることを抽象化する必要があるかもしれないと思うそれはまだではありません。 – Nkosi

+0

ドキュメントストアは単なるファサードです。実際の問題は、例外が発生するのをシミュレートできないという事実です。 –

+0

通常はどこに起こりますか?あなたがモックの1つを呼び出すときにそれを投げるために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

を持っている:私はそうのようにそれを構築しようとしました。上記のコードの2番目のパラメータは、非パブリックデフォルトコンストラクタを探すためにアクティベーターを指定することです

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

よう

何か。

しかし、この方法では、値を初期化することも、Parameteredコンストラクタを使用することもできません。

mogo DBライブラリ用の偽アセンブリを作成し、shimを使用してUpdateOneメソッドを疑似していると仮定します。

この場合、WriteErrorオブジェクトをシムにして、プロパティ "Category"をテストケースに応じて任意の値に戻すことができます。

それは構文は上記のコードでは異なる場合があり

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