使用moq测试对私有方法的调用

时间:2014-01-08 19:03:12

标签: moq

我需要使用Moq测试以下方法。问题是switch语句中调用的每个方法都是私有的,包括最后的PublishMessage。但是这种方法(ProcessMessage)是公开的。我如何测试这个,以便我可以确保根据参数进行调用?请注意,我没有测试私有方法,我只想测试"调用"。我想模拟这些私有方法,并检查它们是否使用安装程序调用,但Moq不支持模拟私有方法。

public void ProcessMessage(DispenserMessageDataContract dispenserMessage)
    {
        var transOptions = new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted };
        using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew, transOptions))
        {
            switch (dispenserMessage.Type)
            {
                case DispenserMessageType.AckNack:
                    UpdateAckNackMessageQueue(dispenserMessage);
                    break;

                case DispenserMessageType.FillRequest:
                    CreateFillRequestMessageQueue(dispenserMessage);
                    break;

                case DispenserMessageType.FillEvent:
                    UpdateFillEventMessageQueue(dispenserMessage);
                    break;

                case DispenserMessageType.RequestInventory:
                    CreateRequestInventoryMessageQueue(dispenserMessage);
                    break;

                case DispenserMessageType.ReceiveInventory:
                    CreateReceiveInventoryMessageQueue(dispenserMessage);
                    break;
            }

            scope.Complete();
        }

        PublishMessage(dispenserMessage);
    }

5 个答案:

答案 0 :(得分:10)

您必须将这些私有方法更改为至少受保护的虚拟对象,然后使用mock.Protected来模拟它们(http://blogs.clariusconsulting.net/kzu/mocking-protected-members-with-moq/)。你不能模仿私人方法。

Moq(以及其他一些框架)使用Castle Project的DynamicProxy在运行时动态生成代理,以便可以截获对象的成员而无需修改类的代码。该拦截只能在公共虚拟和受保护的虚拟方法上完成。

有关详情,请参阅以下网址: http://www.castleproject.org/projects/dynamicproxy/

答案 1 :(得分:3)

您可以在另一个类中提取私有方法并将其公开,然后使用Moq模拟那些并验证它们是否已被调用。

答案 2 :(得分:2)

Moq用于模拟接口中声明的属性和方法,以及类中的抽象属性和方法。

Moq测试背后的想法是测试您的被测试类与世界其他地方(其依赖项)之间的交互。 Moq通过创建接口的“模拟”实现或抽象类的派生来实现这一点。

Moq不能像私有方法那样覆盖现有的实现。这不是Moq的工作方式。

您应该使用所有可能的输入和预期输出测试“ProcessMessage”,或者您应该重构您的类以将调用委托给您可以使用Moq模拟的接口方法。无论如何,测试私有方法是一个坏概念。由于某种原因,它们被保密,这是为了隐藏实现,以便它可以随意改变。

答案 3 :(得分:0)

我更喜欢添加其他类(* Helper)并将所有私有方法移至public。然后,您可以直接轻松地测试您的方法。我没有找到更优雅的方式来做到这一点。

答案 4 :(得分:0)

在某些情况下,您可能需要在进行单元测试的类中更改私有方法的行为。您将需要模拟此私有方法,并使其返回特定情况所需的内容。由于此私有方法位于要测试的类中,因此对其进行模拟将更加具体。您必须使用间谍对象。

间谍对象 间谍是模拟框架可以访问的真实对象。尖顶对象是部分模拟的对象。他们的某些方法是真实的,有些是被嘲笑的。我要特别小心地使用间谍对象,因为您真的不知道其下发生了什么,以及您实际上是在测试类还是模拟版本。

public class PowerMockDemo 
{

    public Point callPrivateMethod() {
        return privateMethod(new Point(1, 1));
    }

    private Point privateMethod(Point point) {
        return new Point(point.getX() + 1, point.getY() + 1);
    }
}

然后,您将模拟间谍对象

希望对您有帮助,

最美好的祝愿