我使用Spock来测试我的java代码,具体测试方法是MnsTemplate的sendMessage方法,单元测试在MnsTemplateTest中,它们在下面的代码中。
在这个单元测试中,我模拟了MNSClient、CloudQueue(mnsClient.getQueueRef(queueName)返回),我期望queue.putMessage方法会执行一次,但结果是它没有执行。
这是java源代码:
public class MnsTemplate {
private MNSClient mnsClient;
public MnsTemplate(MNSClient mnsClient) {
this.mnsClient = mnsClient;
}
public void sendMessage(String queueName, String messageBody) {
mnsClient.getQueueRef(queueName).putMessage(new Message(messageBody));
}
}
及其他相关源码:
public interface MNSClient {
...
public CloudQueue getQueueRef(String queueName);
...
}
public final class CloudQueue {
...
public Message putMessage(Message message) throws ServiceException,
ClientException {
SendMessageAction action = new SendMessageAction(serviceClient,
credentials, endpoint);
SendMessageRequest request = new SendMessageRequest();
request.setMessage(message);
request.setRequestPath(queueURL);
return action.executeWithCustomHeaders(request, customHeaders);
}
...
}
这是Spock单元测试代码:
import spock.lang.Specification
import static org.mockito.Mockito.*
class MnsTemplateTest extends Specification {
MNSClient mnsClient
CloudQueue queue
def setup() {
mnsClient = Mock(MNSClient)
queue = mock(CloudQueue.class)
}
def "sendMessage should send a message to the queue"() {
given:
def mnsTemplate = new MnsTemplate(mnsClient)
1 * mnsClient.getQueueRef("testQueue") >> queue
when:
mnsTemplate.sendMessage("testQueue", "Test Message")
then:
1 * queue.putMessage(new Message("Test Message"))
}
由于CloudQueue.java是final类型,所以我使用mockito-inline来模拟。
执行单元测试时,出现错误:
Too few invocations for:
1 * queue.putMessage(new Message("Test Message")) (0 invocations)
Unmatched invocations (ordered by similarity):
None
at org.spockframework.mock.runtime.InteractionScope.verifyInteractions(InteractionScope.java:110)
at org.spockframework.mock.runtime.MockController.leaveScope(MockController.java:95)
at MnsTemplateTest.sendMessage should send a message to the queue(MnsTemplateTest.groovy:26)
如何修复并使其正确。
jdk是21,spock-core和spock-spring版本是2.4-M4-groovy-4.0
您不能使用 Mockito Mock 并期望 Spock 能够正确处理它。
使用 Spock 模拟。
如果您无法重构生产代码以使其可以正确测试,但需要模拟
final
类,那就“没问题”,Spock 可以做到这一点。 (它内部使用 Mockito 内联模拟生成器,但是以 Spock-y 和 Spock 兼容的方式)。
https://spockframework.org/spock/docs/2.4-M4/all_in_one.html#mock-makers-mockito