You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JUnit5测试抽象类报错:No ParameterResolver registered for构造方法参数

解决JUnit5构造方法参数解析失败的问题

为啥会报错?

JUnit5默认没法自动识别并注入Storage接口类型的构造方法参数——它不知道该传哪个具体实现类的实例,因为没有注册对应的参数解析器来处理这种自定义接口类型。

怎么解决?

方法1:把测试类改成抽象类,让子类提供具体的Storage实例

把AbstractArrayStorageTest改成抽象类,去掉带参数的构造方法,加个抽象方法让子类返回具体的Storage对象,然后在@BeforeEach里完成初始化:

import org.junit.jupiter.api.BeforeEach;
import ru.javawebinar.basejava.storage.Storage;

public abstract class AbstractArrayStorageTest {
    protected Storage storage;

    // 子类必须实现这个方法,返回具体的Storage实例(比如ArrayStorage)
    protected abstract Storage createStorage();

    @BeforeEach
    void setUp() {
        storage = createStorage();
        storage.clear();
        // 这里添加测试用的保存操作,比如存入测试简历
        // storage.save(new Resume("test_id"));
    }

    // 编写你的测试方法,比如testSize、testDelete等
}

然后写具体的实现测试类,比如ArrayStorageTest:

import ru.javawebinar.basejava.storage.ArrayStorage;

public class ArrayStorageTest extends AbstractArrayStorageTest {
    @Override
    protected Storage createStorage() {
        return new ArrayStorage();
    }

    // 还可以添加针对ArrayStorage的特殊测试方法
}

方法2:用参数化测试一次性测试多个Storage实现

如果想在同一个测试类里覆盖多个Storage实现,用JUnit5的参数化测试配合@MethodSource:

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import ru.javawebinar.basejava.storage.Storage;
import ru.javawebinar.basejava.storage.ArrayStorage;
import ru.javawebinar.basejava.storage.AnotherStorage; // 你的其他Storage实现类

import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class AbstractArrayStorageTest {

    // 提供所有需要测试的Storage实例
    static Stream<Storage> storageProvider() {
        return Stream.of(
            new ArrayStorage(),
            new AnotherStorage()
        );
    }

    @ParameterizedTest
    @MethodSource("storageProvider")
    void testClearAndSave(Storage storage) {
        storage.clear();
        // 执行保存操作并验证结果
        Resume testResume = new Resume("test");
        storage.save(testResume);
        assertEquals(1, storage.size());
    }

    // 其他测试方法同理,将Storage作为参数传入即可
}

方法3:自定义参数解析器(不推荐,除非必须)

要是非得保留带参数的构造方法,可以自己写个参数解析器来注入Storage实例,但这种方式比较繁琐,适合特殊场景:

先编写解析器类:

import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolver;
import ru.javawebinar.basejava.storage.Storage;
import ru.javawebinar.basejava.storage.ArrayStorage;

public class StorageParameterResolver implements ParameterResolver {
    @Override
    public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
        // 判断当前参数是否为Storage类型
        return parameterContext.getParameter().getType() == Storage.class;
    }

    @Override
    public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
        // 返回具体的Storage实例,比如ArrayStorage
        return new ArrayStorage();
    }
}

然后在测试类上添加注解,让JUnit使用这个解析器:

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
import ru.javawebinar.basejava.storage.Storage;

@ExtendWith(StorageParameterResolver.class)
public class AbstractArrayStorageTest {
    private Storage storage;

    public AbstractArrayStorageTest(Storage storage) {
        this.storage = storage;
    }

    @BeforeEach
    void setUp() {
        storage.clear();
        // 执行保存操作
    }

    // 测试方法...
}

为啥之前初始化storage会为null?

之前在方法里初始化时出现null,大概率是时机不对——比如在@BeforeEach执行前就调用了storage,或者初始化代码未正确执行(比如放在静态块中但实例化失败)。用上面前两种方法能确保测试方法执行前,storage已经被正确初始化。

内容的提问来源于stack exchange,提问作者Egor Stepanenko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 18:10:31