简体   繁体   English

如何在服务中存根和测试受保护的成员?

[英]How to stub and test protected members in a service?

Pre-story: I am testing a service. 故事前:我正在测试一项服务。 Every n seconds it starts some processes and runs some jobs. 每隔n秒,它将启动一些进程并运行一些作业。 I want to cover the top level of this service (a class which is inherited from ServiceBase) with an integration test. 我想用集成测试来介绍此服务的顶层(从ServiceBase继承的类)。 My goal is to verify: 1. that I can start it, 2. that it sets all timers and 3. creates Job Management Objects to execute jobs (at least to see one execution on the timer). 我的目标是验证:1.我可以启动它,2.它设置了所有计时器,并且3.创建作业管理对象以执行作业(至少在计时器上看到一个执行)。 In the future we want to increase the performance by moving different jobs into different threads, which will also increase complexity of the code.(this is another reason to test it now, while it is still pretty simple) 将来,我们希望通过将不同的作业移到不同的线程中来提高性能,这也将增加代码的复杂性(这是现在对其进行测试的另一个原因,尽管它仍然非常简单)

The question itself: How should I test a service? 问题本身:我应该如何测试服务? All methods and properties in this class are protected or private. 此类中的所有方法和属性都是受保护的或私有的。 And with RhinoMocks I can only stub public members. 使用RhinoMocks,我只能存根公共成员。

Some more thoughts: There is a private member AppJobManagement in this class, which I want to stub. 还有一些想法:此类中有一个私有成员AppJobManagement,我想对此进行存根。 I don't want to use the real instance of this class, as it is connected to the database and may do a lot of unwanted changes when running. 我不想使用此类的真实实例,因为它已连接到数据库,并且在运行时可能会进行很多不必要的更改。 I could make it public for stubbing. 我可以公开进行存根。

But the next issue I have, is how can I assert that the service class works correctly? 但是下一个问题是,如何断言服务类可以正常工作? I will need again make public the methods under the test. 我将需要再次公开测试中的方法。 And this is what I would like to avoid. 这就是我要避免的事情。

Any advice is highly appreciated! 任何建议都非常感谢!

You can create a public or internal constructor to take a dependency on AppJobManagement . 您可以创建一个公共或内部构造函数来依赖AppJobManagement If you can, change the reference to an interface for this class as it may make testing easier. 如果可以,请更改对此类的接口的引用,因为这可能会使测试变得更容易。

public class ServiceToBeTested : ServiceBase
{
    private IAppJobManagement _appJobManagment;

    public ServiceToBeTested()
    {
        _appJobManagment = new AppJobManagement();
    }

    internal ServiceToBeTested(IAppJobManagement appJobManagment)
    {
        _appJobManagment = appJobManagment;
    }
}

If the ServiceToBeTested has a number of protected methods you would like to mock/fake, you should consider another dependency. 如果ServiceToBeTested具有许多您要模拟/伪造的受保护方法,则应考虑另一个依赖项。 For example, instead of: 例如,代替:

public void DoSomethingImportant(string foo)
{
    if (someCondition)
    {
        DoThisOneWay(foo);
    }
    else
    {
        DoThisDifferently(foo);
    }
}

protected void DoThisOneWay(string foo) {}
protected void DoThisDifferently(string foo) {}

You can use another object: 您可以使用另一个对象:

public interface IServiceWorker
{
    void DoThisOneWay(string foo);
    void DoThisDifferently(string foo);
}

public void DoSomethingImportant(string foo)
{
    if (someCondition)
    {
        _worker.DoThisOneWay(foo);
    }
    else
    {
        _worker.DoThisDifferently(foo);
    }
}

The IServiceWorker _worker would be easily mocked. IServiceWorker _worker将很容易被嘲笑。

Update 更新

Another pattern is to use a Factory class to generate these objects. 另一种模式是使用Factory类来生成这些对象。

public interface IAppJobManagementFactory
{
    IAppJobManagement Create(string arg1, int arg2);
}

This too can be mocked. 这也可以被嘲笑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM