测试时自动装配字段为空

时间:2021-07-26 14:28:19

标签: java spring-boot dependency-injection

我正在尝试测试我的应用程序中的一个简单谓词。此谓词使用存储库来检查某些数据,但当我对其进行测试时,存储库始终为 null,即使它在实际上下文中运行良好。

这是谓词:

@Slf4j
public class NameChangePredicate implements ValidationPredicate {

    @Autowired
    NameChangeRepository nameChangeRepository;

    String errorCode;
    GeographicZone zone;

    public NameChangePredicate(String errorCode, GeographicZone zone) {
        super();
        this.errorCode = errorCode;
        this.zone = zone;
    }

    /**
     * Test the condition
     *
     * @param response the {@link ValidationServiceResponse}
     * @return true if valid
     */
    @Override
    public boolean test(ValidationServiceResponse response) {
        if (!StringUtils.isBlank(response.getClass()) && zone != null) {
            List<NameChange> nameChanges = nameChangeRepository.findAllByGeographicZoneId(zone.getId());

            if (nameChanges.stream().anyMatch(n -> n.getClasses().stream().anyMatch(response.getClass()::equalsIgnoreCase))) {
                return true;
            }
        }

        throw new ValidationException(this.errorCode);
    }
}

这是我的简单测试:

@ActiveProfiles("test")
@SpringBootTest
public class NameChangeTest {

    @Autowired
    NameChangeRepository nameChangeRepository;

    @Autowired
    GeographicZoneRepository geographicZoneRepository;

    private GeographicZone zone;

    @BeforeEach
    public void init() {
        ....
    }

    @Test
    public void testNameChangeParameter() {
        final NameChangePredicate predicate = new NameChangePredicate("", zone);
        List<NameChange> list = nameChangeRepository.findAll();
        Assert.assertEquals("There should be 4 NameChange in db", 4, list.size());

        ValidationServiceResponse response = new ValidationServiceResponse();
        response.setBookingClass("C");
        Assert.assertTrue("Name change should be eligible", predicate.test(response));
    }
}

但在测试上下文中,@Autowiredpredicate 存储库是 null,可能是因为它是字段注入。 有没有办法将构造函数注入与其他参数一起使用?

2 个答案:

答案 0 :(得分:1)

试试这个

@Slf4j
public class NameChangePredicate implements ValidationPredicate {

    String errorCode;
    GeographicZone zone;
    NameChangeRepository nameChangeRepository;

    public NameChangePredicate(String errorCode, GeographicZone zone, NameChangeRepository nameChangeRepository) {
        super();
        this.errorCode = errorCode;
        this.zone = zone;
        this.nameChangeRepository = nameChangeRepository;
    }
...
}

@ActiveProfiles("test")
@SpringBootTest
public class NameChangeTest {

    @Autowired
    NameChangeRepository nameChangeRepository;

    ....

    @Test
    public void testNameChangeParameter() {
        final NameChangePredicate predicate = new NameChangePredicate("", zone, nameChangeRepository);
    }
}

已编辑:由于 NameChangePredicate 本身不是 Spring @Component,因此您需要从充当此类客户端的某个其他组件获取对存储库的引用。如果您可以将类设计为组件,那么当您“在真实上下文中”运行它时,Spring 会自动将存储库注入构造函数,就像它在测试中自动装配一样。但当然,在这种情况下,您需要以某种方式摆脱构造函数参数 errorCodezone,这在本示例中似乎不太方便。

答案 1 :(得分:-1)

您在这里混合了两件事:Spring 配置和构造函数。

当您使用构造函数创建 NameChangePredicate 的实例时,Spring 不工作且未对其进行初始化。

不确定如何更正您的示例,但看起来您的设计不太正确。 NameChangePredicate 做两件事:充当谓词并保存两个字段的逻辑。我建议将这两个字段 String errorCode; GeographicZone zone; 分开到一个单独的类中,并以与 NameChangePredicate 相同的方式将其注入 NameChangeRepository