混凝土类中的模拟方法

时间:2013-11-21 22:25:10

标签: c# unit-testing mocking

我有一个类,它执行一系列适用于模型的业务逻辑流程,其中一个是:

public virtual void TryToRunProcess(Model model)
{
    var result = RunCheckMethodOne(model) && RunCheckMethodTwo(model);
    if (result)
        RunMethodThree(model);
}

internal virtual bool RunCheckMethodOne(Model model)
{
    ...
}

internal virtual bool RunCheckMethodTwo(Model model)
{
    ...
}

internal virtual void RunMethodThree(Model model)
{
    ...
}

假设模型及其关联的RunCheckMethodOne()和RunCheckMethodTwo()方法足够复杂以保证自己的单元测试集,我想测试RunCheckMethodOne()和RunCheckMethodTwo()的相应响应是否正确执行RunMethodThree()。

我想通过模拟业务逻辑类,设置两个检查方法来返回特定结果,然后验证第三个方法是否已执行来实现。

我的一项单元测试是:

[TestMethod]
public void TryToRunProcessBothCheckMethodsAreTrueShouldExecuteMethodThreeTest()
{
    var model = new Model();

    var mock = new Mock<ModelBusinessLogic>();
    mock.Setup(r => r.RunCheckMethodOne(It.IsAny<Model>())).Returns(true);
    mock.Setup(r => r.RunCheckMethodTwo(It.IsAny<Model>())).Returns(true);
    mock.Setup(r => r.RunMethodThree(It.IsAny<Model>())).Verifiable();

    mock.Object.TryToRunProcess(model);

    mock.Verify(r => r.RunMethodThree(It.IsAny<Model>()), Times.Once());
}

现在,对我来说这看起来应该可行,但是当我运行这个单元测试时,RunCheckMethodOne()和RunCheckMethodTwo()方法并没有像我期望的那样被模拟;它们实际上是在ModelBusinessLogic类中执行的,而不是返回模拟中设置的值。

我应该在实现中做些什么来确保我可以将所有业务逻辑方法保存在同一个类中(以便不创建过度设计的解决方案)并且仍然能够在业务逻辑类中模拟方法用其他方法练习特定场景?

我正在使用.Net Framework 4.5和Moq 4.0.0.0。

1 个答案:

答案 0 :(得分:1)

你需要做两件事:

  • mock.CallBase = true;
  • 将内部方法设为公共或内部保护(显然不太理想)。

如果你说的话,我认为如果有足够的复杂性来保证个人测试的话,你应该考虑分手。它听起来不像是对我来说过度工程。

修改

您也可以添加

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
如果没有强名,请到你的班级。有关详情,请参阅this question