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

时间:2014-08-04 00:08:30

标签: java java-ee junit

这是我的实体

@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;
    }
}

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;
    }
}

我还有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

<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>  

我的测试看起来像

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);
    }
}  

我在NullPointeException

上获得userService

我错过了什么?

1 个答案:

答案 0 :(得分:1)

注入由Java EE容器在执行时处理。特别是在检查您的代码时,EJB容器将处理UserService的注入,因为它被声明为无状态bean。部署整个应用程序时,将设置容器并且注入工作正常。当执行单元测试时(我猜使用junit)没有启动任何服务,并且任何@Injection最终都会将变量设置为null,因为也不会启动任何容器。

这个想法是单元测试应该只用于测试代码片段,而不像其他类中包含的外部代码。但是,在您的情况下,您似乎需要集成测试,因此,您确实需要所有服务,因为您要检查对象是否在数据库中持久存在。为此,您需要启动一个容器。这样做的好方法是使用Arquillian

例如,在您的情况下,测试应该是这样的:

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);
  }
}