【问题标题】:Test Fails with "when() requires an argument which has to be 'a method call on a mock' " error on maven project(no frameworks used)测试失败,“when() 需要一个参数,该参数必须是'模拟上的方法调用'” Maven 项目上的错误(未使用框架)
【发布时间】:2020-05-12 17:10:55
【问题描述】:

您好,我正在尝试在我的数据库中模拟插入并运行它进行测试。测试失败并出现错误“when() 需要一个参数,该参数必须是‘模拟方法调用’。”我是新手,需要一些帮助。

我没有使用任何框架

编辑测试代码

SaveServlet.java

package com.consentServlets;


import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/SaveServlet")
public class SaveServlet extends HttpServlet {
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out=response.getWriter();
        //Getting the attributes from the UI
        String first_Name = request.getParameter("fname");
        String last_Name = request.getParameter("lname");
        String gender = request.getParameter("gender");
        String age = request.getParameter("age");
        String dob = request.getParameter("dob");

        //Setting the objects to insert the achieved attributes to corresponding the columns of the table
        patient addPatient = new patient();
        addPatient.setLastName(last_Name);
        addPatient.setFirstName(first_Name);
        addPatient.setGender(gender);
        addPatient.setAge(age);
        addPatient.setDoB(dob);

        out.print(" <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css\">");
        //calling the save function from the patientDao class to execute the query
        int status=patientDao.save(addPatient);
        if(status>0){
            out.print("<p>Patient Record saved successfully!</p>");
            request.getRequestDispatcher("index.html").include(request, response);
        }else{
            out.println("Sorry! unable to save record");
        }

        out.close();
    }

}

耐心.java

 package com.consentServlets;
    import java.util.List;
    //creating objects for patient class which will help to store the patient details
    public class patient {  
        private int id;  
        private String first_Name,last_Name,gender,age,dob;  
        public int getId() {  
            return id;  
        }  
        public void setId(int id) {  
            this.id = id;  
        }  
        public String getFirstName() {   
            return first_Name;  
        }  
        public void setFirstName(String first_Name) {  
            this.first_Name = first_Name;  
        }  
        public String getLastName() {  
            return last_Name;  
        }  
        public void setLastName(String last_Name) {  
            this.last_Name = last_Name;  
        }  
        public String getGender() {  
            return gender;  
        }  
        public void setGender(String Gender) {  
            this.gender = Gender;  
        }  
        public String getAge() {  
            return age;  
        }  
        public void setAge(String Age) {  
            this.age = Age;  
        }  
        public String getDoB() {  
            return dob;  
        }  
        public void setDoB(String DOB) {  
            this.dob = DOB;  
        }
    }  

patientDao.java

package com.consentServlets;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List; 

public class patientDao {
    //establishing the connection with the database
    public  Connection getConnection(){  
        Connection con=null;  
        try{  
            Class.forName("com.mysql.jdbc.Driver");
            con=DriverManager.getConnection("jdbc:mysql://localhost:3306/consent_share","root","");
        }catch(Exception e){System.out.println(e);}  
        return con;  
    }  
    public static int save(patient addPatient){  
        int status = 0;  
        //Inserting patient details from UI to Database
        try{                            
            Connection con = new patientDao().getConnection();  
            PreparedStatement ps = con.prepareStatement(  
                    "insert into patient(last_name,first_name,gender,age,dob) values (?,?,?,?,?)");  
            ps.setString(1,addPatient.getLastName());  
            ps.setString(2,addPatient.getFirstName());  
            ps.setString(3,addPatient.getGender());  
            ps.setString(4,addPatient.getAge());
            ps.setString(5,addPatient.getDoB());

            status = ps.executeUpdate();  

            con.close();  
        }catch(Exception ex){ex.printStackTrace();}  

        return status;  
    }  

    public static patient getPatientbyId(int id){  
        patient getPatient = new patient();  
        //selecting a patient record by matching the patient_ID 
        try{ 
            Connection con = new patientDao().getConnection();  
            PreparedStatement ps = con.prepareStatement("select * from patient where patient_id=?");  
            ps.setInt(1,id);  
            ResultSet rs = ps.executeQuery();  
            if(rs.next()){  
                getPatient.setId(rs.getInt(1));  
                getPatient.setLastName(rs.getString(2));  
                getPatient.setFirstName(rs.getString(3));  
                getPatient.setGender(rs.getString(4));  
                getPatient.setAge(rs.getString(5));
                getPatient.setDoB(rs.getString(6)); 
            }  
            con.close();  
        }catch(Exception ex){ex.printStackTrace();}  

        return getPatient;
    }  
    // Fetching all the records from table
    public static List<patient> getAllPatients(){  
        List<patient> list = new ArrayList<patient>();  

        try{  
            Connection con = new patientDao().getConnection();  
            PreparedStatement ps = con.prepareStatement("select * from patient");  
            ResultSet rs = ps.executeQuery();  
            while(rs.next()){  
                patient getAllPatients=new patient();  
                getAllPatients.setId(rs.getInt(1));  
                getAllPatients.setFirstName(rs.getString(3));  
                getAllPatients.setLastName(rs.getString(2));  
                getAllPatients.setGender(rs.getString(4));  
                getAllPatients.setAge(rs.getString(5));
                getAllPatients.setDoB(rs.getString(6));   
                list.add(getAllPatients);  
            }  
            con.close();  
        }catch(Exception e){e.printStackTrace();}  

        return list;  
    }  
}  

patientTest.java

    package com.test;

import static org.junit.Assert.assertEquals;

import java.sql.Connection;
import java.sql.PreparedStatement;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;

import com.consentServlets.patient;
import com.consentServlets.patientDao;

@RunWith(MockitoJUnitRunner.class)

public class patientTest{

    @Mock
    Connection mockCom; 

    @Mock
    PreparedStatement mockSt;

    @InjectMocks
    patientDao mockPatDao;



    @Test
    public void testPatientServlet() throws Exception {


        HttpServletRequest request = Mockito.mock(HttpServletRequest.class);       
        HttpServletResponse response = Mockito.mock(HttpServletResponse.class);    

        /*
         * Mockito.when(request.getParameter("fname")).thenReturn("Rahul");
         * Mockito.when(request.getParameter("lname")).thenReturn("Sen");
         * Mockito.when(request.getParameter("gender")).thenReturn("Male");
         * Mockito.when(request.getParameter("age")).thenReturn("20");
         * Mockito.when(request.getParameter("dob")).thenReturn("1996-07-24");
         */

        patient patientSave = new patient();
        patientSave.setLastName("Rahul");
        patientSave.setFirstName("Sen");
        patientSave.setGender("Male");
        patientSave.setAge("20");
        patientSave.setDoB("1996-07-24");

        //String query = "";

    Mockito.when(new patientDao().getConnection()).thenReturn(mockCom);
        Mockito.when(mockCom.prepareStatement(Matchers.anyString())).thenReturn(mockSt);
        Mockito.when(mockSt.executeUpdate()).thenReturn(1);

        String URI = "/SaveServlet";
        //int status=patientDao.save(patientSave);
        int actualStatus= mockPatDao.save(patientSave);
        int expectedStatus = 1;

        //Mockito.when(insert.save(patientSave)).thenReturn(1);
        assertEquals(expectedStatus,actualStatus);

    }
}

堆栈跟踪

org.mockito.exceptions.misusing.MissingMethodInvocationException: 

when() 需要一个参数,该参数必须是“模拟方法调用”。 例如: when(mock.getArticles()).thenReturn(articles);

此外,出现此错误的原因可能是: 1.你存根:final/private/equals()/hashCode()方法。 这些方法不能被存根/验证。 不支持在非公共父类上声明的模拟方法。 2. 在 when() 中,你不会在 mock 上调用方法,而是在其他对象上调用。

at com.test.patientTest.testPatientServlet(patientTest.java:62)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.mockito.internal.runners.DefaultInternalRunner$1$1.evaluate(DefaultInternalRunner.java:46)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:77)
at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:83)
at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)

【问题讨论】:

  • 旁注 - 按照 Java 类名的约定,如果以大写字母开头。请遵循,它大大提高了可读性。
  • 您正在使用几个框架...测试框架 jUnit,模拟框架 Mockito 仅举其中两个。
  • 添加更新的测试代码

标签: java junit mockito


【解决方案1】:

正如堆栈跟踪所说,when 只能用于模拟对象。

when() 需要一个参数,该参数必须是“模拟方法调用”。

虽然以下代码使用了when,但该对象未被模拟。

patientDao insert = new patientDao();

Mockito.when(insert.save(patientSave)).thenReturn(status);

您需要模拟insert 对象或删除Mockito.when(insert.save(patientSave)).thenReturn(status);,因为它不需要。

【讨论】:

  • 如果我理解正确,insert 应该是被测试的对象,所以没有必要嘲笑它。
  • 那么你不应该用when来嘲笑它。您应该让save 方法被调用。
  • 或删除Mockito.when(insert.save(patientSave)).thenReturn(status);。不要认为它是必要的。
  • 如果他模拟了insert,它会修复错误但会使测试变得毫无用处——为什么有人要测试模拟是否正常工作?
  • @ChristineShaji 我认为您缺少一些与测试相关的基本术语的知识。 mock 是一个假对象,其中没有逻辑,只做所说的事情。如果您模拟一个 patientDao,您将不会测试该类,而是一些与您的类实现几乎没有任何关系的假实例(没有逻辑)。因此,您不能这样做 Mockito.when(insert...Mockito.when(new patientDao()...
【解决方案2】:

在异常消息中它说:

在 when() 中,你不会在 mock 上调用方法,而是在其他对象上调用方法。

在你的代码中你有:

patientDao insert = new patientDao();
...
Mockito.when(insert.save(patientSave)).thenReturn(status);

我不确定你想用第二行实现什么,但它会导致错误并且没用 - 你应该删除它。

其实整个测试我都不清楚。

如果我理解正确,insert 应该是被测试的对象,所以模拟它没有意义,你必须处理一个实际的对象。

【讨论】:

  • 抱歉,我正在更新新代码。那是一个未保存的
【解决方案3】:

如果您使用 KOIN,请在 gradle 的依赖项中包含:

dependencies {
    ...
    testImplementation "org.koin:koin-test:2.0.0"
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-08
    • 2012-02-29
    • 2023-02-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多