当前位置: 首页 > 知识库问答 >
问题:

Spring@Autowired构造函数在测试类中实例化时会导致@Value返回null

洪光霁
2023-03-14

我在一个服务中使用了一个自动连接的构造函数,当在测试类中实例化时,它会导致@Value注释返回null。自动关联依赖项直接解决了这个问题,但项目遵循使用基于构造函数的自动关联的惯例。我的理解是,在测试类中实例化服务并不是从Spring IoC容器创建服务,这会导致@Value返回null。有没有一种方法可以使用基于构造函数的自动连接从IoC容器创建服务,而不必直接访问应用程序上下文?

示例服务:

@Component
public class UpdateService {

   @Value("${update.success.table}")
   private String successTable;

   @Value("${update.failed.table}")
   private String failedTable;

   private UserService userService

   @Autowired
   public UpdateService(UserService userService) {
      this.userService = userService;
   }
}

测试服务示例:

@RunWith(SpringJUnite4ClassRunner.class)
@SpringApplicationConfiguration(classes = {TestApplication.class})
@WebAppConfiguration
public class UpdateServiceTest {

   private UpdateService updateService;

   @Mock
   private UserService mockUserService;

   @Before
   public void setUp() {
      MockitoAnnotations.initMocks(this);

      updateService = new UpdateService(mockUserService);

   }
}

共有2个答案

屠君墨
2023-03-14

@Value由属性占位符配置器填充,该配置器是Spring上下文中的后处理器。由于您的UpdateService不是上下文的一部分,因此不会处理它。

您的设置看起来有点像单元测试和集成测试的混合体。对于单元测试,您根本不需要spring上下文。只需将@Value带注释的成员包设置为受保护,并对其进行设置,或者使用ReflectionTestUtils。setField()(均显示):

public class UpdateServiceTest {

   @InjectMocks
   private UpdateService updateService;

   @Mock
   private UserService mockUserService;

   @Before
   public void setUp() {
      MockitoAnnotations.initMocks(this);
      ReflectionTestUtils.setField(updateService, "successTable", "my_success");
      updateService.failedTable = "my_failures";
   }
}

对于联调器,所有接线应在Spring前完成。

为此,我添加了一个提供mock用户服务的内部配置类(仅当您的上下文中有任何其他用户服务时,@Primary才适用),mock存储在这里的一个静态成员中,以便在以后的测试中简单地访问mock。

@RunWith(SpringJUnite4ClassRunner.class)
@SpringApplicationConfiguration(classes = {TestApplication.class, UpdateServiceTest.TestAddOn.class})
@WebAppConfiguration
public class UpdateServiceTest {

   @Autowired
   private UpdateService updateService;

   private static UserService mockUserService;



   static class TestAddOn {
      @Bean
      @Primary
      UserService updateService() {
        mockUserService = Mockito.mock(UserService.class);
        return mockUserService;
      }
   }
}
颜嘉福
2023-03-14

要使@Value工作updateService应该在spring上下文中。

Spring框架集成测试的最佳实践是在测试上下文中包含应用程序上下文,并在测试中自动装配测试源:

...
public class UpdateServiceTest  { 
    @Autowired 
    private UpdateService updateService;
    ...

模拟用户服务

选项,将userService更改为protected,并考虑测试类和源类在同一个包中。

@Before
public void setUp() {
   MockitoAnnotations.initMocks(this);

   updateService.userService = mockUserService;
}

选项与反射与白盒:

@Before
public void setUp() {
   MockitoAnnotations.initMocks(this);

   Whitebox.setInternalState(updateService, 'userService', mockUserService);
}
 类似资料:
  • 问题内容: 到目前为止,我在构造函数中有一个类 的功能是在数据库中查找特定的电子邮件地址。当我将标识符设置为某些电子邮件时,我确定它不在数据库中;第一个IF被传递,并转到第一个ELSE。这里的构造函数应该返回FALSE; 但是,它返回具有所有NULL值的类的对象! 我如何防止这种情况?谢谢 编辑: 谢谢大家的回答。那太快了!我看到OOP方式是抛出异常。因此,抛出一个问题,我的问题发生了变化,我应该

  • 我是Spring的新手。我创建了一个bean类和一个配置文件,如下所示: Beans.xml Employee.java 当我尝试使用Application Context获取bean时,它会给出以下异常: 线程“main”组织中出现异常。springframework。豆。工厂BeanCreationException:创建在类路径资源[Problem.xml]中定义的名为“employee”的

  • 问题内容: 如何从Java的构造函数中获取实例化对象? 我想为某些GUI类存储对父对象的引用,以模拟事件冒泡-调用父处理程序-但我不想更改所有现有代码。 问题答案: 简短的回答:Java没有办法做到这一点。(您可以找到哪个班级叫您,但以下较长的答案在大多数情况下也适用于您。) 长话大说:依赖于被调用的地方,魔术地表现不同的代码几乎总是一个坏主意。这会使必须维护您代码的人感到困惑,并且严重损害了您的

  • 我有一个用@service注释的类(HttpHandler)。我正在为这个服务类编写单元测试用例。我在测试类中使用@Autowired注释来获取服务的对象。但是,当我运行单元测试时,它返回NullPointerException。有人能帮帮我吗? 下面是服务类的代码:

  • 问题内容: 我有这个代码。对象构造函数是否有可能以某种方式失败,从而为它分配了一个值,并在构造函数返回后释放了该对象? 问题答案: 假设您使用的是PHP 5,则可以在构造函数中引发异常: 为了清楚起见,您可以将其包装在静态工厂方法中: 顺便说一句,某些版本的PHP 4允许您在构造函数中将$ this设置为NULL,但我认为这从未得到正式批准,并且最终删除了“功能”。

  • 测试时,我在使用application.properties值时遇到问题。 这是我的代码: 这和预期的一样工作。它用在我的updateSubscription方法中,正确的值来自application.properties 问题出在我的测试中,当我使用这个类时,这个值没有被实例化并抛出一个错误 但这会引发错误:lateinit属性defaultPackageForFCMInstance尚未初始化