试图为JUnit生成Spring的@Autowired字段注入错误

时间:2014-10-03 01:50:19

标签: spring junit spring-3 spring-test spring-4

我正在使用Spring 4.0.7,并且正在使用JUnit进行测试。

关于DI Spring提供@Autowired在三个地方使用

  • 构造
  • 设定器
  • 字段

我总是首先解决这两个问题,为什么从来没有第三个选项?

因为我记得早就读过不应该使用场注射,因为它对测试有负面影响。 JUnit失败了。

注意:仅针对测试是问题所在。对于运行时或生产一切顺利

目标:出于演示/学术目的,我想产生这个问题。

我有以下内容:

存储库

public interface PersonRepository extends JpaRepository<Person, String>{

}

服务

@Service
@Transactional
@Profile("failure")
public class PersonFailTestServiceImpl implements PersonService {

    private static final Logger logger = ...

    @Autowired
    private PersonRepository personRepository; 

其他服务(致电或使用上述服务)

@Service
@Transactional
@Profile("failure")
public class PersonFailTestProcessImpl implements PersonProcess {

    private static final Logger logger = ...

    @Autowired
    private PersonService personService;

如何看待这两种服务基于Field Injection。

现在测试:

如何加载bean

    @Configuration
    @ComponentScan( basePackages={"com.manuel.jordan.server.infrastructure"},
                    basePackageClasses={PersonProcess.class,PersonRepository.class, PersonService.class})
    public class CentralConfigurationEntryPoint {

    }

    @ContextConfiguration(classes=CentralConfigurationEntryPoint.class)
    public class CentralTestConfigurationEntryPoint {
    }

现在有两个测试类

@Transactional
@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles({"development","failure"})
public class PersonServiceImplDevelopmentFailureTest extends CentralTestConfigurationEntryPoint {

    @Autowired
    private PersonService personService;

    @Test
    public void savePerson01(){
        Person person01 = PersonFactory.createPerson01();
        personService.save(person01);
        personService.printPerson(personService.findOne("1"));
    }

@Transactional
@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles({"development","failure"})
public class PersonProcessImplDevelopmentFailureTest extends CentralTestConfigurationEntryPoint{

    @Autowired
    private PersonProcess personProcess;

所有测试方法都通过,全部为绿色。我不知道我是否遗漏了某些东西,或者通过Spring 4解决了问题

2 个答案:

答案 0 :(得分:2)

如果这是你的前提或问题

  

因为我记得早就读过有关野外注射的内容   不应该使用,因为它有负面影响   测试。 JUnit失败了。

那时你想错了。使用字段注入没有任何内在错误,绝对不会导致JUnit测试失败。如果bean存在,Spring将能够注入它,无论它是在构造函数,setter方法还是字段中。

由于您已激活failure个人资料,因此将找到您的PersonFailTestServiceImpl bean。

答案 1 :(得分:1)

我想我可以提供帮助。您在此处发布的示例代码是系统/集成测试的一个很好的示例,而不是UNIT测试。

如果您是UNIT测试PersonFailTestProcessImpl,则必须通过代码自行设置personRepository依赖项。但它是私人的,所以你怎么做?您不能使用构造函数或setter,因为没有提供。这就是“难以进行单元测试”的意思。

Java 5+提供了一种通过反射(所谓的特权访问器)设置这样的私有变量的方法。基本上,您获取类,获取声明的字段,调用其setAccessible方法,然后您可以直接设置其值。有些库会为您执行这些步骤,但关键是与X.setSomething()相比,这是一个痛苦;

因此,在私有字段上使用@Autowired没有任何“使jUnit失败”。但是,构建没有用于建立依赖关系的构造函数或setter的对象模型是不必要的约束。