当前位置: 首页 > 知识库问答 >
问题:

spock测试中被模仿的java类没有被执行

王成化
2023-03-14
    null

第一个类如下所示:

public class RequestProcessor {

   private String request;

   public RequestProcessor(String aRequest) {
      this.request = request;
   }

   public String processRequest() {
       String response ;
       //do something here

       try {
           if(condition meets) {
              response = executeRequest();
           }
       } catch ( various exceptions... ) {
           System.out.println("something went wrong...");
       }
   }

   private String executeRequest() throws <<exceptions thrown by DatabaseQuery>> {
       //do something here
       DatabaseQuery queryResult = new DatabaseQuery(request)
   }
}

我试图为这个RequestProcessor类编写一个Spock测试,该类依赖于DatabaseQuery。我正在考虑模拟DatabaseQuery类,以便单独测试RequestProcessor类。

正在调用RequestProcessorProcessRequest()方法,该方法依赖于另一个私有方法。该方法将使用DatabaseQuery获取实际查询结果。这就是我的Spock测试的样子:

class RequestProcessorSpec extends Specification {

    //Class to be tested
    RequestProcessor requestProcessor

    //Dependencies
    DatabaseQuery dbquery

    def "Given a valid request, dbquery's executeQuery method is called" () {
        given: "a valid request"
            def queryRequest = '{"info1":"value1","info2":"value2","query":"select * from users"}'

        and: "mock the DBQuery class"
            dbquery = Mock(DatabaseQuery)

        and: "create a new request"
            requestProcessor = new RequestProcessor(queryRequest)

        when: "the request is processed"
            requestHandler.processRequest()

        then: "dbquery executeQuery method is called"
            1 * dbquery.executeQuery(_ as String)
    }
 }
    null

共有1个答案

满勇军
2023-03-14

首先,即使我对示例代码进行了简化并创建了自己的虚拟DatabaseQuery类,示例代码也无法工作,因为这里至少有三个错误:

  • 在构造函数中有this.request=request(自赋值),但应该是this.request=arequest;.
  • 在测试中,您有requestHandler.processRequest(),但应该是requestProcessor.processRequest().
  • 方法executeRequest()不返回指定的字符串。所以我只能推测,实际上它在DatabaseQuery上调用了另一个方法,以便将查询结果转换为字符串.

解决了这个问题之后,让我们看看你的测试到底有什么根本问题。

我想你的测试只是规格过高。为什么要检查另一个类中的特定方法是否从私有方法调用(间接调用)?您不直接测试私有方法,而是通过调用公共方法覆盖它们的代码,您的测试已经这样做了。

如果要覆盖catch块,只需确保请求导致正确的异常。也许您需要为此模拟数据库连接,并确保它将预期的结果返回到DatabaseQuery。我没有看到足够的代码来准确地说。

现在让我们假设你绝对想检查这个交互,不管我之前说过什么。您需要做什么取决于情况(代码中没有显示):

在任何情况下,都需要使DatabaseQuery可注入。您只需向类中添加一个成员和另一个setter即可。

现在,根据交互dbquery.executeQuery(_as String)的来源,您有了一个岔路口:

  1. 如果从databasequery外部调用该方法,则可以插入一个普通的mock.
  2. 如果从databasequery内部调用该方法,则需要注入spy,因为模拟不会调用其他内部方法,比如原始对象,因为--嗯,它只是一个模拟。
package de.scrum_master.query;

public class DatabaseQuery {
  private String request;

  public DatabaseQuery(String request) {
    this.request = request;
  }

  public String executeQuery(String request) {
    return request.toUpperCase();
  }

  public String getResult() {
    return executeQuery(request);
  }
}
package de.scrum_master.requests;

import de.scrum_master.query.DatabaseQuery;

public class RequestProcessor {
  private String request;
  private DatabaseQuery databaseQuery;

  public RequestProcessor(String aRequest) {
    this.request = aRequest;
    databaseQuery = new DatabaseQuery(request);
  }

  public String processRequest() {
    return executeRequest();
  }

  private String executeRequest() {
    return databaseQuery.executeQuery(request);
    //return databaseQuery.getResult();
  }

  public void setDatabaseQuery(DatabaseQuery databaseQuery) {
    this.databaseQuery = databaseQuery;
  }
}
package de.scrum_master.requests

import de.scrum_master.query.DatabaseQuery
import spock.lang.Specification

class RequestProcessorTest extends Specification {
  //Class to be tested
  RequestProcessor requestProcessor

  //Dependencies
  DatabaseQuery dbquery

  def "Given a valid request, dbquery's executeQuery method is called" () {
    given: "a valid request"
    def queryRequest = '{"info1":"value1","info2":"value2","query":"select * from users"}'

    and: "mock the DBQuery class"
    dbquery = Mock(DatabaseQuery)
    //dbquery = Spy(DatabaseQuery, constructorArgs: [queryRequest])

    and: "create a new request"
    requestProcessor = new RequestProcessor(queryRequest)
    requestProcessor.databaseQuery = dbquery

    when: "the request is processed"
    requestProcessor.processRequest()

    then: "dbquery executeQuery method is called"
    1 * dbquery.executeQuery(_ as String)
  }
}

现在测试工作了,包括交互检查。

情况2:executeQuery(String)从自己的类内部调用

您看到requestprocessorrequestprocessortest中的两行注释掉了吗?只需使用它们,然后像这样注释掉另外两个:

  private String executeRequest() {
    //return databaseQuery.executeQuery(request);
    return databaseQuery.getResult();
  }
    and: "mock the DBQuery class"
    //dbquery = Mock(DatabaseQuery)
    dbquery = Spy(DatabaseQuery, constructorArgs: [queryRequest])
 类似资料:
  • 我是Spock框架的新手,在使用抽象java测试类时遇到了问题。 我想要的是一个groovy测试类,它用一些常用的方法扩展一些其他java抽象类,这些方法反过来扩展规范类。 当我运行GroovyTest类时,我得到以下错误: Org.SpockFramework.Runtime.InvalidSpecException:规范“org.my.package.AbstractTest”未正确编译(Sp

  • 执行testng xml时,它在套件中只执行1个测试 基本测试- 登录测试-

  • 我试图测试一个使用@inject注入成员的Java类。 我想测试一下 我的类没有显式构造函数

  • 我想现在,如果有可能模仿一个类一样 我们的业务逻辑在代码中的某个地方用< code>new myClass()创建了这个对象,因此我不能访问创建的对象来模拟这些方法。有没有办法替换整个类或者覆盖那些方法。我正在使用mockito,我只找到了这样做的例子 我们不能使用 PowerMock,因为它与我们的测试环境不兼容。 欢迎任何建议。

  • 我正在为扩展了B类的a类编写单元测试。我正在使用Mockito,我想模拟一个组织。slf4j。这两个类都可以使用。问题是,当类A从类B调用方法时,模拟记录器没有被注入到类B中,所以我得到了一个NPE。有没有办法成功地测试这一点?

  • 我这样做是为了得到想要的结果