在测试类中测试私有方法

时间:2018-08-16 15:27:16

标签: c# unit-testing nunit fakeiteasy

我正在测试一个类,该类具有私有方法,并从公共方法内部调用。我希望能够伪造此测试方法,以便从不调用实际方法。

public class Service
{
    public int MethodA(int a)
    {
        SaveToDB(a);
        if (validate())
        {
                return a * 5;
        }
        else 
        {
            return 0;
        }
    }

  private bool validate(int a)
  {
        if (a > 100)
          return true;
        else 
          return false; 
   }

    private bool SaveToDB()
    {
     // some logic to save to the database..
     return true;
    }
 }

[FixtureTest]
public ServiceTest
{
//assuming we are using nunit and fakeiteasy..
[Test]
public void MethodA_Should_Return_Zero_when_Provided_100()
{
    var fakeService = new Service;
    var result = fakeservice.MethodA(101);
    // I want to avoid the call SaveToDB() in the test how do I go about doing this..

 //if this was a public method I could create a test stub and test like with a statement like 
 A.call(() => ServiceA.SaveToDB().Return())
// however this is a private function what should I do???
}
}

1 个答案:

答案 0 :(得分:0)

最简单的答案是使受SaveToDB保护的虚拟环境并在测试项目中创建可测试的派生类。

public class FakeTestService : Service
{
    ...

    protected override bool SaveToDB()
    {
        // do nothing

        return true;
    }
}

在测试中使用FakeTestService,将执行“真实” MethodA,但SaveToDB将不执行任何操作。但是,真正的答案是使用某种形式的控制反转将可以通过模拟库模拟的接口注入数据库。

public class Service
{
    public int MethodA(int a)
    {
        DatabaseThinger.SaveToDB(a);
        if (validate())
        {
            return a * 5;
        }
        else 
        {
            return 0;
        }
    }

    private IDatabaseThinger DatabaseThinger;

    public Service(IDatabaseThinger databaseThinger)
    {
        DatabaseThinger = databaseThinger;
    }
}

因此将数据库功能移出该类,然后将其放在接口后面。然后,您可以在测试中插入实际上无法连接到数据库的IDatabaseThinger选择的实现。