【问题标题】:Test if method in ClassA has been called from another method in ClassA测试是否从 Class 中的另一个方法调用了 Class A 中的方法
【发布时间】:2015-09-17 09:13:33
【问题描述】:

可以使用Moq and dependency injection 测试方法是否被调用。但是,是否可以测试一个类中的一个方法是否调用同一个类中的另一个方法?

例如,我想测试如果我记录了某个异常,是否也会记录一条信息消息。

方法是:

public void Error(string message, Exception exception, long logId = 0)
{
    var int32 = (int)logId;
    Info("Id was converted to an int so that it would fit in the log: " + logId, int32);
    Error(message, exception, int32);
}

这是我对它进行单元测试的尝试。测试失败,有什么办法可以做到吗?

void logging_an_error_with_a_long_id_also_logs_info()
{
    var mock = new Mock<ILogger>();
    var testedClass = new Logger();
    var counter = 0;

    testedClass.Error("test" + counter++, new Exception("test" + counter), Int64.MaxValue);

    mock.Verify(m => m.Info(It.IsAny<string>(), It.IsAny<int>()));
}

由于InfoError 方法在同一个类(ClassA)中,我不相信我可以将ClassA 作为依赖项传递给ClassA。那么它不需要测试吗?

【问题讨论】:

标签: c# unit-testing moq


【解决方案1】:

你能做的最好的事情就是让Infovirtual。这将允许您创建 Mock&lt;Logger&gt;,设置 CallBase = true,并验证是否调用了 Info

var mock = new Mock<Logger> 
{
    CallBase = true
};

mock.Object.Error("test" + counter++, new Exception("test" + counter), Int64.MaxValue);

mock.Verify(m => m.Info(It.IsAny<string>(), It.IsAny<int>()));

这样,您仍在调用Error 的实际实现,但您已使用Moq 来验证Info 方法是否被调用。

【讨论】:

  • +1 这在使用 Mock 时有效,因为需要真正的类。不适用于接口 Mock.
【解决方案2】:

感觉就像你在尝试测试错误的东西。从Error 方法调用您的类上的Info 方法并不重要,重要的是Info 方法的行为会发生。它是如何发生的是该类的实现细节。

如果我的数学课有两个函数:

public int Mult(int x, int y) {
    return x*y;
}

public int Sqr(int x) {
    return Mult(x,y);
}

我不会测试调用Sqr 调用Mult 函数,我会测试Sqr(4)==16。该计算是在 Sqr 方法中进行还是在该类的其他方法中进行并不重要。

虽然 @Andrew 的 solution 可能是您所追求的,但嘲笑您正在测试的课程往往会导致紧密耦合、脆弱的测试。

如果通过观察它的副作用来测试调用是不切实际的,那么这可能表明实现可以使用一些重构。

【讨论】:

  • 说可能有更好的方法比提供更好的方法更容易
  • @Hoppe 虽然这是真的,但为了提供一种更好的方式,通常需要比提供的更多上下文(例如,我不知道您的 Error 或 Info 方法的内容是什么)。有时可以做的最好的事情是指出另一个方向,这在某些情况下会打开一扇门,让他们以不同的方式看待他们的问题。..
猜你喜欢
  • 2021-11-04
  • 1970-01-01
  • 1970-01-01
  • 2011-11-20
  • 1970-01-01
  • 1970-01-01
  • 2015-11-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多