如何对线程进行单元测试,这需要花费一些时间来执行操作 [英] How to Unit-Test Thread which takes time to perform action

查看:81
本文介绍了如何对线程进行单元测试,这需要花费一些时间来执行操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有Thread,它在程序运行并轮询队列时运行,并检查它是否有对象,如果是,则在该对象上调用方法

I have Thread which runs while the program runs and polls a queue and check whether it has object and if yes then it calls method on the object

这是代码:

while(isRunning){
        synchronized (loginQueue) {
            if(loginQueue.peek() != null) {
                Object[] loginObjectWithConnection = loginQueue.poll();
                tryLogin(loginObjectWithConnection);
            }
        }
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
}

这是tryLogin方法

Here is the tryLogin method

private void tryLogin(Object[] loginObjectWithConnection) {
        LoginPacket packet = (LoginPacket)loginObjectWithConnection[0];
        Connection connection = (Connection)loginObjectWithConnection[1];

        try {
            if(playerDataService.arevalidCredentials(packet.getUserName(), packet.getPassword())) {

                if(!playerDataService.isPlayerBanned(packet.getUserName())){ //Player exists in the system

                    communicationService.sendTCP(connection, packetFactory.makeLoginFailurePacket(StringConstants.PLAYER_BANNED));

                } else{ //Player is not banned

                }
            } else { // Player does not exist
                communicationService.sendTCP(connection, packetFactory.makeLoginFailurePacket(StringConstants.INVALID_USER));
            }
        } catch (SQLException e) {
            communicationService.sendTCP(connection, packetFactory.makeLoginFailurePacket(StringConstants.SERVER_ERROR));
            e.printStackTrace();
        }
}

现在,我的问题是我想测试这些服务方法的调用,但是当我运行单元测试时,它们将无法正常工作,因为到达tryLogin需要花费时间,直到JUnit失败.我尝试使用Thread.sleep(),但我知道这样做不是正确的方法,因为它有时会失败并有时会通过.

Now my problem is that I want to test the invocations of these service methods but when I run the unit tests they won't work as it takes time to reach the point of tryLogin and till then JUnit fails. I tries using Thread.sleep() but I know it is not the right way to do it as it fails sometimes and pass sometimes.

这是单元测试中的内容

@Test
public void theExpectedMessageShouldBeSentIfUserIsBanned() throws InterruptedException, SQLException {
    //Arrange
    when(moqLoginQueue.peek()).thenReturn(object);
    when(moqLoginQueue.poll()).thenReturn(object);
    LoginFailurePacket packet = new LoginFailurePacket(StringConstants.PLAYER_BANNED);
    when(moqPacketFactory.makeLoginFailurePacket(StringConstants.PLAYER_BANNED)).thenReturn(packet);
    when(moqPlayerDataService.arevalidCredentials(anyString(), anyString())).thenReturn(true);
    when(moqPlayerDataService.isPlayerBanned(anyString())).thenReturn(true);

    //Act
    loginManager.start();
    Thread.sleep(10); //Dirty hack -.-

    //Assert
    verify(moqCommunicationService).sendTCP(any(Connection.class), eq(packet));
}

推荐答案

该系统无法以当前形式进行测试:良好的测试质量包括:

The system is untestable in the current form: among good test qualities there are:

  • 易于其他程序员理解
  • 其他程序员很难破解
  • 运行速度快

您要测试的逻辑部分是LoginManager.tryLogin,这在您的代码段中是私有的.如果要公开记录它(测试是一种记录文件:它们说明了系统的行为方式),则必须公开.

The piece of logic you want to test is LoginManager.tryLogin, which is private in your snippet. If you want to publicly document it (tests are kind of documentation: they state how the system should behave), it has to be public.

我建议将所有逻辑移到新类中的方法上:Authentication.attempt()(我建议一个不可变的对象和一个不带任何参数的方法-有人说OO设计中参数的最佳数量为零)

I suggest to move all that logic to a method in a new class: Authentication.attempt() (I suggest an immutable object and a method that does not take any argument - someone says the optimal number of arguments in OO design is zero).

现在测试是可行的,我还认为您应该摆脱LoginManager.start()中的所有代码:只需使用ExecutorService并提交身份验证尝试-这样,您将拥有更快的程序和更少的代码来进行测试,因为困难(棘手的部分)是由Java管理的.

Now that testing is feasible, I also think you should get rid of all that code in LoginManager.start(): simply use an ExecutorService and submit authentication attempts - this way you'll have a faster program and less code to test, because the hard (and tricky) part is managed by Java.

这篇关于如何对线程进行单元测试,这需要花费一些时间来执行操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆