2017-10-02 11 views
3

私のロガーが例外を適切に記録していることを確認できるように、例外処理の周りに単体テストを作成しようとしています。私は私のテストのために、以下に私が持っているモックフレームワークとMicrosoft.Extensions.Logging.ILoggerとしてNSubstituteを使用しています:NS代替ILogger .NETコア

[Fact] 
public void LogsExcpetionWhenErrorOccursInCreate() 
{ 
    var newUser = new UserDataModel 
    { 
     FirstName = "Rick", 
     MiddleName = "Jason", 
     LastName = "Grimes", 
     Email = "[email protected]", 
     Created = new DateTime(2007, 8, 15) 
    }; 
    var exception = new Exception("Test Exception"); 
    // configure InsertOne to throw a generic excpetion 
    _mongoContext.InsertOne(newUser).Returns(x => { throw exception; }); 

    try 
    { 
     _collection.Create(newUser); 
    } 
    catch 
    { 
     // validate that the logger logs the exception as an error 
     _logger.Received().LogError(exception.Message); 
    } 
} 

次のような方法でログをテストするために:

public UserDataModel Create(UserDataModel user) 
{ 
    try 
    { 
      return MongoContext.InsertOne(user);     
    } 
    catch(Exception e) 
    { 
      _logger?.LogError(e.Message); 
      throw new DataAccessException("An error occurred while attempting to create a user.", e); 
     } 

}

私のテストがで失敗します次のエラー:

Message: NSubstitute.Exceptions.ReceivedCallsException : Expected to receive a call matching: 
    Log<Object>(Error, 0, Test Exception, <null>, Func<Object, Exception, String>) 
Actually received no matching calls. 
Received 1 non-matching call (non-matching arguments indicated with '*' characters): 
    Log<Object>(Error, 0, *Test Exception*, <null>, Func<Object, Exception, String>) 

これがなぜ失敗するのかわかりませんなぜなら、エラーメッセージであっても、呼び出しは同じであるからです。

ありがとうございます!

更新:

public UserCollectionTest() 
{ 
    _mongoContext = Substitute.For<IMongoContext<UserDataModel>>(); 
    _logger = Substitute.For<ILogger>(); 
    // create UserCollection with our mock client 
    _collection = new UserCollection(_mongoContext, _logger); 
} 
+0

ILogger代替品を作成して注入する方法を明確にしてください。 –

+0

私はテストのコンストラクタでポストを更新しました。これがサブを注入しています。 –

答えて

3

のlogErrorはILoggerです方法ではないので、あなたは、このことをチェックしようとすると:ここ

私はモックロガーを注入していますこれはどこで、テストのためのコンストラクタですメソッドは、NSubstituteが何らかの形でそれを処理しようとする特定のパラメータで呼び出されました(私は正確には分かりません)。

のlogError拡張メソッドのコードは次のとおりです。

public static void LogError(this ILogger logger, string message, params object[] args) 
{ 
    if (logger == null) 
    throw new ArgumentNullException("logger"); 
    logger.Log<object>(LogLevel.Error, (EventId) 0, (object) new FormattedLogValues(message, args), (Exception) null, LoggerExtensions._messageFormatter); 
} 

ですから、Logメソッドが呼び出されたことを確認する必要があります。

私はあなたの例を単純化しました。アイデアははっきりしているはずです。

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 

     var logger = Substitute.For<ILogger>(); 
     try 
     { 
      Create(logger); 
     } 
     catch 
     { 
      logger.CheckErrorMessage("My Message"); 
     } 
    } 

    public string Create(ILogger logger) 
    { 
     try 
     { 
      throw new Exception("My Message"); 
     } 
     catch (Exception e) 
     { 
      logger?.LogError(e.Message); 
      throw new Exception("An error occurred while attempting to create a user.", e); 
     } 
    } 
} 

public static class TestExtensions 
{ 
    public static void CheckErrorMessage(this ILogger logger, string message) 
    { 
     logger.Received().Log(
      LogLevel.Error, 
      Arg.Any<EventId>(), 
      Arg.Is<object>(o => o.ToString() == message), 
      null, 
      Arg.Any<Func<object, Exception, string>>()); 
    } 
} 
関連する問題