使用mock来测试void方法

时间:2015-06-12 21:17:30

标签: .net unit-testing moq xunit

我有一个班级

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

1 个答案:

答案 0 :(得分: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