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

单元测试时静态元模型属性为空

乐正迪
2023-03-14

我在一个外部包中有@Entity类,它也有静态元模型。在我的应用程序的服务类中,我使用这些元模型和EntityManager/criteria builder/criteria query来检索我的数据。这在运行应用程序时工作良好。然而,当运行单元测试时,我的元模型和它们的属性总是空的。

密码

package com.example.core.entities;

@Entity
@Table(schema = "lookup", name="BookingSystem")
public class BookingSystem implements ILookupEntity, IAuditEntity, Serializable {
  @Id
  @GeneratedValue(strategy = IDENTITY)
  @Column(name = "id")
  public Integer id;

  @Column(name = "name")
  public String name;

  @Column(name = "code")
  public Integer code;
}

package com.example.core.entities;

@Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
@StaticMetamodel(BookingSystem.class)
public abstract class BookingSystem_ {
  public static volatile SingularAttribute<BookingSystem, Integer> id;
  public static volatile SingularAttribute<BookingSystem, Integer> code;
  public static volatile SingularAttribute<BookingSystem, String> name;
}

我的应用程序服务类中的使用情况。。。

package com.example.bookingsystem;

@Service
public class BookingService {
  @PersistenceContext
  private EntityManager entityManager;

public void saveBooking(Booking booking) {
//...
  RepositoryQueryBuilder<BookingSystem> bookingSystemSelector = new RepositoryQueryBuilder<>(entityManager, BookingSystem.class);
  List<BookingSystem> bookingSystems = bookingSystemSelector
      .and(BookingSystem_.code, booking.bookingSystem.code) //<-- Here "BookingSystem_.code" is null.
      .getResultList();
  //...
  }
}

“RepositoryQueryBuilder”类只是一个实用程序构建器类,它包装了EntityManager、CriteriaBuilder等。基本上是按照这个例子建模的... JPA标准谓词条件

单元测试代码...

package com.example.bookingsystem;

public abstract class BaseTestSetup {
  @InjectMocks
  protected BookingService bookingService;

  protected EntityManager entityManager = PowerMockito.mock(EntityManager.class);
  protected CriteriaBuilder criteriaBuilder = PowerMockito.mock(CriteriaBuilder.class);
  protected CriteriaQuery<BookingSystem> criteriaQuery = PowerMockito.mock(CriteriaQuery.class);
  protected Root<BookingSystem> root = PowerMockito.mock(Root.class);

  protected void arrange() {
    when(entityManager.getCriteriaBuilder()).thenReturn(criteriaBuilder);
    when(criteriaBuilder.createQuery(BookingSystem.class)).thenReturn(criteriaQuery);
    when(criteriaQuery.from(Matchers.<Class<BookingSystem>>any())).thenReturn(root);
    when(criteriaQuery.from(Matchers.<EntityType<BookingSystem>>any())).thenReturn(root);
}

}

@RunWith(PowerMockRunner.class)
public class BookingServiceTest extends BaseTestSetup {
  @BeforeClass
  @Override
  public void arrange() {
    super.arrange();

    //...
}

@Test
public void doIt() {
    Booking booking = new Booking();
    booking.id = 12345;
    booking.bookingSystem = new BookingSystem();
    booking.bookingSystem.id = 1;
    booking.bookingSystem.code = 106000;

    bookingService.saveBooking(booking);
  }
}

我看过这个JPA/Hibernate静态元模型属性未填充——NullPointerException,但是解决方案似乎是“确保实体及其元模型在同一个包中”,但是正如你所看到的,两者都已经在我的“com.example.core.entities”包中了。

我在代码中使用了所有bean和注释驱动的配置(没有持久性或上下文xml文件)。至于测试,我在IntelliJ中使用TestNG和PowerMock。

看起来好像在单元测试期间没有拾取元模型。任何想法。

共有3个答案

仲孙磊
2023-03-14

不需要手动初始化。你应该遵守以下规则:

    < li >元模型类应声明为抽象类。 < li >元模型类应该与它们描述的实体类在同一个包中; < li >它们应该具有与它们描述的实体类相同的名称,后跟一个下划线(例如,Product是实体,Product_是元模型类); < li >如果一个实体从另一个实体或从一个映射的超类继承,它的元模型类应该从描述它的直接超类的元模型类继承(例如,如果SpecialProduct扩展Product,它扩展PersistentObject,那么SpecialProduct_应该扩展Product_它应该扩展PersistentObject_)。
金令秋
2023-03-14

与其创建自己的类,我建议让Mockito来为你做这项工作。

 @Mock // declare a mock along the others you might have
 private SingularAttribute<BookingSystem, Integer> code;

 @Before
 public void setUp() throws Exception { 
     // fill metamodel with it
     BookingSystem_.code = code;
 }

然而,值得一提的是,将元模型引入服务层并不是一个很好的实践,您宁愿将它们向下推到DAO方法。

屠坚壁
2023-03-14

加载hibernate时填充静态元模型类。因此,您可以在测试中配置hibernate上下文,或者在方法执行之前手动填充属性。在您的代码中,您可以执行:

@Test
public void doIt() {
    BookingSystem_.code = new SingularAttributeMock<BookingSystem, Integer>();
    bookingService.saveBooking(booking);
  }
}

SingularAttributeMock类可以定制创建,以便在您的测试中使用它。您也可以使用SingularAttribute类的任何其他实现。

public class SingularAttributeMock<X, Y> implements SingularAttribute<X, Y> {
   //Overriding methods of SingularAttribute...
}
 类似资料:
  • 问题内容: 阅读并学习单元测试,尝试理解下面的文章,该文章解释了静态函数调用的困难。 我不清楚这个问题。我一直认为静态函数是在类中舍入实用函数的一种好方法。例如,我经常使用静态函数调用进行初始化,即: //阅读这篇文章后,我现在的目标是… 但是,我为此课程编写的几十个测试是相同的。我什么都没改变,他们仍然都过去了。难道我做错了什么? 该帖子的作者指出: 静态方法的基本问题是它们是过程代码。 我不知

  • 我需要junit测试一段代码,但它从不同类调用的GsonConverter是静态方法,我无法更改。我不知道如何进行,因为我不能嘲笑它,因为它是静态的。 下面是带有静态方法的类

  • 问题内容: 考虑到没有引入不能再次测试的包装器的方法,则不能在单元测试开发环境中使用静态的类/方法/属性? 另一种情况是,在单元测试目标中使用静态成员时,无法模拟静态成员。因此,在测试单元测试目标时,您必须测试静态成员。当静态成员执行计算时,您想隔离它。 问题答案: 测试静态方法与测试任何其他方法没有什么不同。将静态方法作为 依赖关系 在另一个经过测试的模块中会引发问题(如前所述- 您无法使用免费

  • 问题内容: 我想将JPA2 Criteria API与元模型对象一起使用,这似乎很简单: 但是这个Root.get总是抛出一个。是由Hibernate自动生成的,看起来像 但显然从未有人居住。 我是否缺少框架初始化步骤? 编辑: 这是崩溃时我如何使用JPA和元模型的摘要: (是一个类,所以我就在前面)和相关的堆栈跟踪: 编辑2: 在JBoss EntityManager指南中,我可以看到 当构建H

  • 我有一个这样的方法。 > 如果我模拟记录器,是否必须将方法更改为post(字符串json,记录器记录器)?否则,如何使此模拟与该方法交互?

  • 我正试着用摩卡和柴对我的猫鼬模型做一个简单的测试 错误:超过2000毫秒的超时时间。对于异步测试和挂钩,确保调用“done()”;如果返回promise,请确保它已解决 我想摩卡已经改变了,因为它一直在与以前的项目合作。我错过了什么? 模型方法: