【问题标题】:Using mock to test a void method使用 mock 测试 void 方法
【发布时间】:2015-06-12 21:17:29
【问题描述】:

我有课

public class NLogRuleComposer : INLogComponentComposer
{
    private LoggingConfiguration _nLogLoggingConfiguration;

    //TODO:  think we need to constructor-inject the logging config 
    public void ComposeComponent(LoggerModel loggerModel
        , LoggingConfiguration nLogLoggingConfiguration
        , string loggerFullName)
    {
        _nLogLoggingConfiguration = nLogLoggingConfiguration;
        var ruleName = loggerFullName;
        var minimumLevel = LogLevel.FromString(loggerModel.level.min_level);
        var maximumLevel = LogLevel.FromString(loggerModel.level.max_level);
        var allTargetsWithLayout = nLogLoggingConfiguration.AllTargets.OfType<TargetWithLayout>().ToList();
        var targetWithoutStackTrace = allTargetsWithLayout
            .FirstOrDefault(x => x.Name.Contains("WithoutStacktrace"));
        var targetWithStackTrace = allTargetsWithLayout.FirstOrDefault(x => x.Name.Contains("WithStacktrace"));
        CreateDefaultLevelFilter(ruleName, maximumLevel.Name, minimumLevel, targetWithoutStackTrace); 
    }

    public void CreateDefaultLevelFilter(string ruleName, string maximumLevelName
        , LogLevel minimumLevel, TargetWithLayout targetWithoutStackTrace)
    {
        var filter = new ConditionBasedFilter();
        filter.Action = FilterResult.Log;
        filter.Condition = "(level <= LogLevel." + maximumLevelName + ")";
        var loggerRule = new LoggingRule(ruleName, targetWithoutStackTrace);
        loggerRule.Filters.Add(filter);
        _nLogLoggingConfiguration.LoggingRules.Add(loggerRule);
    }

现在我想测试CreateDefaultLevelFilter 方法,但它是无效的。我不知道如何测试它并测试什么。可以使用 Mock 吗?

未完成的代码:

public class NLogRuleComposerUnitTests
{
    [Theory]
    [InlineData("MyLoggerName")]
    public void NLogRuleComposer_Should_Create_A_LoggingRule(
        string expectedLogger)
    {
        var nLogRuleComposerMock = new Mock<INLogComponentComposer>();
        var nLogTargetMock = new Mock<TargetWithLayout>();
        nLogRuleComposerMock.Setup(x => x.ComposeComponent(It.IsAny<LoggerModel>()
    , It.IsAny<LoggingConfiguration>()
    , It.IsAny<string>()))
    .Verifiable();
    }
}

【问题讨论】:

    标签: .net unit-testing moq xunit


    【解决方案1】:

    如果没有依赖注入,您将很难测试那段代码。创建这样的实例

    var filter = new ConditionBasedFilter();
    

    这使得单元测试成为不可能,因为作为副作用,您也在测试类ConditionBasedFilter。理想情况下,您的单元测试不应该测试除方法结果或行为之外的任何内容。应该模拟外部依赖项。

    我会做什么:

    • 创建工厂以构建所有相关类的实例。
    • 在构造函数中注入工厂接口
    • 模拟工厂可以控制它们返回的内容,以便您可以验证,例如,正确的信息设置为filter

    如果你没有注入依赖的习惯,你应该开始养成这个习惯 :) 没有它,就不可能正确地进行单元测试。

    这是一个如何测试ConditionBasedFilter 属性的示例

    var conditionBasedFilter = new ConditionBasedFilter();
    var conditionBasedFilterFactoryMock = new Mock<IConditionBasedFilterFactory>
    var conditionBasedFilterFactoryMock
         .Setup(f => Create())
         .Returns(conditionBasedFilter);
    

    然后,您在 CreateDefaultLevelFilter 方法中使用这样的工厂

    // this factory is injected on contructor
    var filter =  _conditionBasedFilterFactory.Create(); 
    

    在测试结束时,您断言过滤器设置为 ActionCondition 的正确值。同样适用于loggerRule

    【讨论】:

    • ConditionBasedFilter 来自 NLog 库。 See here。而且我确实有ComponentComposer的工厂,只是不知道如何在这里申请。
    • 如果您使用模拟工厂创建ConditionalBaseFilter,您可以返回您控制的实例。让我在我的答案中添加示例
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-27
    • 1970-01-01
    • 2012-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多