如何断言调用具体类上的私有方法(TypeMock/NMock/等..)?

发布于 2024-08-23 13:33:15 字数 2043 浏览 10 评论 0原文

我正在尝试为下面的类中的“IsUnique”函数编写一个单元测试,如下所示:

class Foo
{
    public bool IsUnique(params...)
    {
       ValidateStuffExists(params);
       return CheckUniqueness(params);
    }

    private void ValidateStuffExists(params)
    {
      //does some validation
    }

    private bool CheckUniqueness(params)
    {
       //does logic to determine if its unique per params
       return result;
    }

}

我想在这里测试的唯一事情是调用 ValidateStuffExists 和 CheckUniqueness 并传递参数。这就是这个函数所做的一切,所以这就是我要测试的全部(我将改变“仅测试公共行为”伪规则并在这里测试私有方法,因为它要么有一个大的复杂方法/测试,要么测试 2 个私有方法)方法)。

我对任何模拟库持开放态度。我使用 NMock 并且不认为它适合该任务 - 所以我下载了 TypeMock,因为我已经阅读并听说这是最好的,它甚至可以模拟具体的类/非接口方法调用...

我我在测试中做了类似的事情,它在“Isolate.WhenCalled”行抛出异常:

        CrmEntityUniqueValidator_Accessor target = new CrmEntityUniqueValidator_Accessor(); // TODO: Initialize to an appropriate value
        DynamicEntity entity = null; // TODO: Initialize to an appropriate value
        string[] propertyNames = null; // TODO: Initialize to an appropriate value

        bool tru = true;
        Isolate.WhenCalled(() => target.CheckUniqueness(entity, propertyNames, null, null)).WillReturn(tru);

        target.ValidatePropertiesExist(entity, propertyNames);

        Isolate.Verify.WasCalledWithArguments(() => target.ValidatePropertiesExist(entity, propertyNames));
        Isolate.Verify.WasCalledWithArguments(() => target.CheckUniqueness(entity, propertyNames, null, null));

这会抛出一个异常,如 “*** WhenCalled 不支持使用方法调用作为参数。”

即使我能够使用 CLR 类做同样的事情 - 我可以模拟 DateTime.Now 这样做(代码有效):

        DateTime endOfWorld = new DateTime(2012, 12, 23);
        Isolate.WhenCalled(() => DateTime.Now).WillReturn(endOfWorld);
        DateTime dt = DateTime.Now;

        Assert.AreEqual(dt, endOfWorld);

有人有任何建议吗?我是否必须将这两个方法分成一个单独的类并创建一个接口是唯一的方法?或者使我的方法/测试复杂化???我这里一定缺少一些东西...非常感谢您提前提供的任何帮助。

编辑:我想我正在尝试模拟类中的 2 个私有方法以进行一个单元测试。我怎样才能做到这一点,而不必将这两个方法拆分为单独的类/接口?

I am trying to write a unit test for the 'IsUnique' function in the class below that looks like this:

class Foo
{
    public bool IsUnique(params...)
    {
       ValidateStuffExists(params);
       return CheckUniqueness(params);
    }

    private void ValidateStuffExists(params)
    {
      //does some validation
    }

    private bool CheckUniqueness(params)
    {
       //does logic to determine if its unique per params
       return result;
    }

}

The only thing I want to test here is that ValidateStuffExists and CheckUniqueness is called and passed the arguments. That's all this function does so it's all I'm going to test (I'll bend the 'test public behavior only' psuedo-rule and test the private methods here, because its either have one big complicated method/tests or testing 2 private methods).

I am open to any mocking library. I use NMock and didn't think it was up for the Task - so I downloaded TypeMock as I've done reading and heard that this was the best and that it could mock out even concrete classes / non interface method calls...

I'm doing something like this in my test and it throws exception at the 'Isolate.WhenCalled' line:

        CrmEntityUniqueValidator_Accessor target = new CrmEntityUniqueValidator_Accessor(); // TODO: Initialize to an appropriate value
        DynamicEntity entity = null; // TODO: Initialize to an appropriate value
        string[] propertyNames = null; // TODO: Initialize to an appropriate value

        bool tru = true;
        Isolate.WhenCalled(() => target.CheckUniqueness(entity, propertyNames, null, null)).WillReturn(tru);

        target.ValidatePropertiesExist(entity, propertyNames);

        Isolate.Verify.WasCalledWithArguments(() => target.ValidatePropertiesExist(entity, propertyNames));
        Isolate.Verify.WasCalledWithArguments(() => target.CheckUniqueness(entity, propertyNames, null, null));

This throws an exception like "*** WhenCalled does not support using a method call as an argument."

Even though I'm able to do the same thing with a CLR class - I can mock out DateTime.Now doing this (code works):

        DateTime endOfWorld = new DateTime(2012, 12, 23);
        Isolate.WhenCalled(() => DateTime.Now).WillReturn(endOfWorld);
        DateTime dt = DateTime.Now;

        Assert.AreEqual(dt, endOfWorld);

Anyone have any advice here? Do I have to split these 2 methods into a seperate class and make an interface is the only way? or complicate my method/tests??? There must be something I'm missing here... Thanks much for any help in advance.

EDIT: I guess I'm trying to mock out the 2 private methods in the class for the one unit test. How could I do this without having to split out those 2 methods into a seperate class / interface?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

春庭雪 2024-08-30 13:33:16

RhinoMocks 有 AssertWasCalled 方法可以用于保证一个方法调用另一个方法......但我不确定您是否可以在您正在单元测试的同一类的私有函数上执行此操作。我认为只有当您想要存根的两个方法位于注入的另一个依赖项类中时,您才可以这样做。

RhinoMocks has the AssertWasCalled method which may serve the purpose of guaranteeing that a method calls another method... but I'm not sure you can do that on a private function of the same class you are unit testing. I think you could only do that if the two methods you wanted to stub were in another dependency class that was injected.

七禾 2024-08-30 13:33:15

尝试
Isolate.NonPublic.WhenCalled(object,"非公共方法").IgnoreCall

或 Isolate.Verify.NonPublic.WasCalled(object,"方法"..

try
Isolate.NonPublic.WhenCalled(object,"nonpublic method").IgnoreCall

or Isolate.Verify.NonPublic.WasCalled(object,"method"..

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文