Java 如何解决;争论是不同的;错误-单元测试

Java 如何解决;争论是不同的;错误-单元测试,java,junit,mockito,Java,Junit,Mockito,我想用mockito为我的addTask方法编写单元测试。 下面是包含此方法的类 package controller; import model.Task; import model.User; import repository.TaskActions; import repository.UserActions; import java.sql.SQLException; import java.util.List; public class ToDoEngine { private

我想用mockito为我的addTask方法编写单元测试。 下面是包含此方法的类

package controller;

import model.Task;
import model.User;
import repository.TaskActions;
import repository.UserActions;

import java.sql.SQLException;
import java.util.List;

public class ToDoEngine {
private TaskActions taskActions;
private UserActions userActions;
private User connectedUser;

public ToDoEngine(UserActions userStorage, TaskActions taskStorage) {
    this.taskActions = taskStorage;
    this.userActions = userStorage;
}

public boolean signIn(String username, String password) throws SQLException {
    connectedUser = new User(username, password);
    if (!userActions.signIn(connectedUser)) {
        return false;
    }
    connectedUser.setID(retrieveConnectedUserID(connectedUser));
    return true;
}

private int retrieveConnectedUserID(User connectedUser) throws SQLException {
    return userActions.retrieveUserID(connectedUser);
}

public void addTask(String taskName) throws SQLException {
    taskActions.addTask(new Task(taskName), connectedUser);
}

}
以下是我的尝试。不幸的是,我有错误。下面,我将向您介绍stacktrace:

package controller;

import model.Task;
import model.User;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import repository.TaskActions;
import repository.UserActions;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class ToDoEngineTest {

@Mock
TaskActions taskActionsMock;
@Mock
UserActions userActionsMock;
private ToDoEngine toDoEngine;


@Before
public void setup() {
    MockitoAnnotations.initMocks(this);
    toDoEngine = new ToDoEngine(userActionsMock, taskActionsMock);
}

@Test
public void addTask() throws SQLException {
    Task taskName = new Task("wash");
    User user = new User("admin","123");
    toDoEngine.addTask("wash");
    verify(taskActionsMock).addTask(taskName,user);
}
}
堆栈跟踪

Argument(s) are different! Wanted:
taskActionsMock.addTask(
    Task(taskName=wash),
    model.User@1b71f500
);
-> at controller.ToDoEngineTest.addTask(ToDoEngineTest.java:68)
Actual invocation has different arguments:
taskActionsMock.addTask(
    Task(taskName=wash),
    null
);
-> at controller.ToDoEngine.addTask(ToDoEngine.java:40)

Comparison Failure:  <Click to see difference>

Argument(s) are different! Wanted:
taskActionsMock.addTask(
    Task(taskName=wash),
    model.User@1b71f500
);
-> at controller.ToDoEngineTest.addTask(ToDoEngineTest.java:68)
Actual invocation has different arguments:
taskActionsMock.addTask(
    Task(taskName=wash),
    null
);
-> at controller.ToDoEngine.addTask(ToDoEngine.java:40)
at controller.ToDoEngineTest.addTask(ToDoEngineTest.java:68)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
...
package model;

import lombok.*;

@RequiredArgsConstructor
@Getter
@Setter
@EqualsAndHashCode

public class User {

private final String name;
private final String password;
private int ID;
}
用户

Argument(s) are different! Wanted:
taskActionsMock.addTask(
    Task(taskName=wash),
    model.User@1b71f500
);
-> at controller.ToDoEngineTest.addTask(ToDoEngineTest.java:68)
Actual invocation has different arguments:
taskActionsMock.addTask(
    Task(taskName=wash),
    null
);
-> at controller.ToDoEngine.addTask(ToDoEngine.java:40)

Comparison Failure:  <Click to see difference>

Argument(s) are different! Wanted:
taskActionsMock.addTask(
    Task(taskName=wash),
    model.User@1b71f500
);
-> at controller.ToDoEngineTest.addTask(ToDoEngineTest.java:68)
Actual invocation has different arguments:
taskActionsMock.addTask(
    Task(taskName=wash),
    null
);
-> at controller.ToDoEngine.addTask(ToDoEngine.java:40)
at controller.ToDoEngineTest.addTask(ToDoEngineTest.java:68)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
...
package model;

import lombok.*;

@RequiredArgsConstructor
@Getter
@Setter
@EqualsAndHashCode

public class User {

private final String name;
private final String password;
private int ID;
}

提前谢谢你的帮助D

您的
verify
方法指定希望使用特定的
taskName
user
对象调用
addTask

verify(taskActionsMock).addTask(taskName,user);
但是,由于您连接的用户为
null
,因此此预期失败。 如果您不关心连接的用户,可以使用匹配器告诉Mockito忽略其实际值。例如

verify(taskActionsMock).addTask(ArgumentMatchers.eq(taskName), ArgumentMatchers.any());

或者,如果您确实关心用户,只需将ToDoEngine设置为已连接用户。

在您的测试用例中,您正在尝试验证对该方法的调用:

public void addTask(String taskName) throws SQLException {
    taskActions.addTask(new Task(taskName), connectedUser);
}
为此:

User user = new User("admin","123");
...
verify(taskActionsMock).addTask(taskName,user);
失败消息

Actual invocation has different arguments:
taskActionsMock.addTask(
    Task(taskName=wash),
    null
);
。。。告诉我们测试调用中的
connectedUser
的值为
null

查看您的代码,
ToDoEngine
connectedUser
成员由对
signIn()
方法的调用填充,但是您的测试用例没有调用该方法,因此当您的测试调用
addTask
时,
connectedUser
为空

因此,如果您不需要/不想测试是否为
addTask
提供了正确的用户,那么只需将验证调用更改为:
verify(taskActionsMock)。addTask(taskName,null)


但是,这感觉像是一个小步,因此您应该确保
connectedUser
不为null,并且是您在测试用例中提供给验证调用的值。

好吧……我添加了这行代码,没有删除任何内容:
toDoEngine.sign(“admin”,“123”)。考试通过了,但我不确定我的方式是否正确。我是否需要
User User=新用户(“admin”、“123”)行了吗?我在问,因为我不明白,在
signIn
方法中,我创建了一个新的user对象,然后创建了另一个user对象。好的,您的更改解决了这一点:“您应该确保connectedUser不为null,并且是您在测试用例中提供给verify调用的值”,因此您的测试通过了。这是有效的,我认为您不需要对
addTask()
测试进行任何更改。您可以通过在
userActionsMock.signIn()
上设置期望值来验证
signIn
中的行为(当该值返回true时,connectedUser将有一个id,否则不会),但这是一个单独的测试。是的。但我的问题是,在
signIn
方法中,我创建了用户的新对象(connectedUser)然后,我创建了另一个用户对象,并将其传递到这里
verify(taskActionsMock).addTask(taskName,user)。我们如何知道这是
connectedUser
的同一个对象?它不是同一个对象,但您不是在断言它是同一个对象,而是在断言(通过调用
verify()
)用户的两个不同实例是相等的。因此,您的测试预期name=admin和password=123的用户将被传递到
addTask
,这就是您的代码所做的,因此测试通过。