使用 Rhino Mocks 删除公共函数内私有函数的依赖

发布于 2024-08-31 08:43:29 字数 651 浏览 8 评论 0原文

我是嘲笑的新手,并从 Rhino Mocks 开始。我的场景是这样的..在我的类库中,我有一个公共函数,在其中我有一个私有函数调用,它从服务获取输出。我想删除私有函数依赖项。

public class Employee
    {        
        public virtual string GetFullName(string firstName, string lastName)
        {
            string middleName = GetMiddleName();
            return string.Format("{0} {2} {1}", firstName, lastName,middleName );
        }

        private virtual string GetMiddleName()
        {
            // Some call to Service

            return "George";
        }
    }

但这不是我的真实场景,我只是想知道如何删除 GetMiddleName() 函数的依赖关系,并且我需要在单元测试时返回一些默认值。

注意:我无法在这里更改私有函数..或包含接口..保留函数本身,有什么方法可以模拟它。谢谢

I am new to mocking, and have started with Rhino Mocks. My scenario is like this..in my class library i have a public function and inside it i have a private function call, which gets output from a service.I want to remove the private function dependency.

public class Employee
    {        
        public virtual string GetFullName(string firstName, string lastName)
        {
            string middleName = GetMiddleName();
            return string.Format("{0} {2} {1}", firstName, lastName,middleName );
        }

        private virtual string GetMiddleName()
        {
            // Some call to Service

            return "George";
        }
    }

This is not my real scenario though, i just wanted to know how to remove dependency of GetMiddleName() function and i need to return some default value while unit testing.

Note : I won't be able to change the private function here..or include Interface..Keeping the functions as such, is there any way to mock this.Thank

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

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

发布评论

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

评论(2

記憶穿過時間隧道 2024-09-07 08:43:29

问题是这部分:“私有函数调用,从服务获取输出”。应该注入该服务,以便您可以模拟它。如果它创建服务本身的具体实例,那么我认为 Rhino 无法帮助您。

TypeMock 也许可以帮助你 - 我相信它可以让你模拟任何东西 ,但代价是更具侵入性。

您不应该删除调用私有方法的依赖关系,而应该删除该私有方法内部的依赖关系。如果你做不到这一点,那么如果没有像 TypeMock 这样的东西,你的代码根本无法测试。

The problem is this part: "a private function call, which gets output from a service". That service should be injected, so that you can mock it out. If it creates a concrete instance of the service itself, then I don't think Rhino can help you.

TypeMock may be able to help you - I believe that lets you mock out anything, but at the cost of being more invasive.

You shouldn't remove the dependency of calling the private method, you should remove the dependency within that private method. If you can't do that, your code simply isn't testable without something like TypeMock.

爱要勇敢去追 2024-09-07 08:43:29

一种可能的解决方案是使用提取和覆盖模式从被测类派生一个可测试类,并覆盖 private 方法(该方法应该是您的测试中的 private 以外的方法)例如,私有方法不能是虚拟 - 也许您的意思是受保护?)以允许您覆盖该方法。

public class Employee
{        
    public virtual string GetFullName(string firstName, string lastName)
    {
        string middleName = GetMiddleName();
        return string.Format("{0} {2} {1}", firstName, lastName,middleName );
    }

    protected virtual string GetMiddleName()
    {
        // Some call to Service

        return "George";
    }
}

///<summary>
///Testable Employee class
///</summary>
public class TestableEmployee : Employee
{    
    public string MiddleName;

    public virtual string GetFullName(string firstName, string lastName)
    {
        string middleName = GetMiddleName();
        return string.Format("{0} {2} {1}", firstName, lastName,middleName );
    }

    protected override string GetMiddleName()
    {
        // provide own implementation to return 
        // property that we can set in the test method

        return MiddleName;
    }
}

[TestMethod]
public GetFullName_ReturnsSetName()
{
    var testEmployee = new TestableEmployee();
    string firstName = "first";
    string middleName = "middle";
    string lastName = "last";

    TestableEmployee.MiddleName = middleName;

    string fullName = GetFullName(firstName, lastName);

    Assert.AreEqual(string.Format("{0} {2} {1}", 
                    firstName, lastName, middleName ), 
                    fullName
                    );
}

如果 GetMiddleName() 是服务调用的包装器,那么将服务接口作为 Employee 类的属性可能是一个更可测试的设计 这样,您可以使用提取和覆盖模式或使用控制反转 (IoC) 容器(例如 Unity温莎城堡

One possible solution is to use the Extract and Override pattern to derive a testable class from the class under test and override the private method (which should be something other than private in your example as a private method cannot be virtual - perhaps you meant protected?) to allow you to override the method.

public class Employee
{        
    public virtual string GetFullName(string firstName, string lastName)
    {
        string middleName = GetMiddleName();
        return string.Format("{0} {2} {1}", firstName, lastName,middleName );
    }

    protected virtual string GetMiddleName()
    {
        // Some call to Service

        return "George";
    }
}

///<summary>
///Testable Employee class
///</summary>
public class TestableEmployee : Employee
{    
    public string MiddleName;

    public virtual string GetFullName(string firstName, string lastName)
    {
        string middleName = GetMiddleName();
        return string.Format("{0} {2} {1}", firstName, lastName,middleName );
    }

    protected override string GetMiddleName()
    {
        // provide own implementation to return 
        // property that we can set in the test method

        return MiddleName;
    }
}

test method

[TestMethod]
public GetFullName_ReturnsSetName()
{
    var testEmployee = new TestableEmployee();
    string firstName = "first";
    string middleName = "middle";
    string lastName = "last";

    TestableEmployee.MiddleName = middleName;

    string fullName = GetFullName(firstName, lastName);

    Assert.AreEqual(string.Format("{0} {2} {1}", 
                    firstName, lastName, middleName ), 
                    fullName
                    );
}

if GetMiddleName() is wrapper around a service call, then it might be a more testable design to have the service interface as a property of the Employee class. This way, you can mock out the service type using the Extract and Override pattern or using an Inversion of Control (IoC) container like Unity or Castle Windsor.

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