简体   繁体   English

单元测试:@Inject不注入服务

[英]Unit Test: @Inject not injecting service

here is my entity 这是我的实体

@Entity
public class User {
    @Id
    private String id;
    private String externalUserId;
    private String email;
    private String clientId;
    private String clientSecret;
    private boolean active;

    public User(@Nonnull final String externalUserId, @Nonnull final String email,
                @Nonnull final String clientId, @Nonnull final String clientSecret, final boolean active) {
        id = UUID.randomUUID().toString();
        this.externalUserId = externalUserId;
        this.email = email;
        this.clientId = clientId;
        this.clientSecret = clientSecret;
        this.active = active;
    }
}

and a UserService 和一个UserService

import javax.annotation.Nonnull;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceUnit;

@Stateless
public class UserService {
    @PersistenceUnit
    private EntityManager entityManager;


    @Nonnull
    public User createUser(@Nonnull final User user) {
        entityManager.persist(user);
        return user;
    }
}

I also have DBConfig as 我也有DBConfig作为

import javax.annotation.sql.DataSourceDefinition;
import javax.ejb.Stateless;

@DataSourceDefinition(
        name = "java:app/oauth/testDB",
        className = "org.h2.jdbcx.JdbcDataSource",
        url = "jdbc:h2:mem:test"
)
@Stateless
public class DBConfig {
}

test/src/main/resources/persistence.xml as test/src/main/resources/persistence.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">
    <persistence-unit name="testDB" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <class>com.self.oauth.persistence.entities.User</class>
    </persistence-unit>
</persistence>  

My test looks like 我的测试看起来像

public class UserTest {

    @Inject
    private UserService userService;

    @Test
    public void testUser() {
        final User user = new User(UUID.randomUUID().toString(), "test@test.com", "clientId", "clientSecret", true);
        userService.createUser(user);
        assertTrue(true);
    }
}  

and I get NullPointeException on userService 我在userService上得到NullPointeException

What am I missing? 我想念什么?

Injection is handled by a Java EE Container in execution time. 注入在执行时由Java EE容器处理。 In particular and checking your piece of code, an EJB container would handle the injection of UserService since it is declared to be a Stateless bean. 特别是在检查您的代码段时,EJB容器将处理UserService的注入,因为它被声明为无状态Bean。 When you deploy your entire application a container is set and injection works fine. 部署整个应用程序时,将设置一个容器,并且注入工作正常。 When executing unit tests (I guess using junit) none of the services are launched, and any @Injection will end up with the variable set to null, because no container will be launched either. 当执行单元测试(我猜想使用junit)时,不会启动任何服务,并且任何@Injection最终都会将变量设置为null,因为也不会启动任何容器。

The idea is that unit tests should be only used for testing pieces of code independently of external ones like the one contained in other classes. 想法是,单元测试应仅用于独立于外部代码(如其他类中的代码)之外的代码段进行测试。 However, in your case it looks like you want an integration test, so, you really need all services to be up since you want to check that an object is persisted in the database. 但是,在您的情况下,您似乎需要进行集成测试,因此,您确实需要启动所有服务,因为您要检查对象是否在数据库中保持不变。 For that, you need you need to launch also a container. 为此,您还需要启动一个容器。 A good way of doing that, is using Arquillian . 一个很好的方法是使用Arquillian

For instance, in your case, the test should be something like this: 例如,在您的情况下,测试应该是这样的:

package org.arquillian.example;

import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(Arquillian.class)
public class  UserTest{

  @Deployment
  public static JavaArchive createDeployment() {
    return ShrinkWrap.create(JavaArchive.class)
      .addClass(UserService.class)
      .addClass(User.class)
      .addClass(DBConfig.class)
      .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
  }

  @Inject
  private UserService userService;

  @Test
  public void testUser() {
    final User user = new User(UUID.randomUUID().toString(), "test@test.com", "clientId", "clientSecret", true);
    userService.createUser(user);
    assertTrue(true);
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM