0

我是 mocking 新手,并且从 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() 函数的依赖关系,并且我需要在单元测试时返回一些默认值。

注意:我将无法在这里更改私有函数..或包含接口..保留这些函数,有没有办法模拟这个。谢谢

4

2 回答 2

2

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

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

您不应该删除调用私有方法的依赖关系,您应该删除该私有方法中的依赖关系。如果您不能这样做,那么您的代码在没有 TypeMock 之类的情况下根本无法测试。

于 2010-05-02T08:03:05.193 回答
0

一种可能的解决方案是使用提取和覆盖模式从被测类派生一个可测试的类并覆盖该private方法(这应该是private您的示例之外的其他方法,因为private方法不能virtual- 也许您的意思是protected?)以允许您覆盖方法。

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) 容器(如UnityCastle Windsor )来模拟服务类型。

于 2010-05-02T08:34:30.457 回答