Reputation: 91949
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
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
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
<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(), "[email protected]", "clientId", "clientSecret", true);
userService.createUser(user);
assertTrue(true);
}
}
and I get NullPointeException
on userService
What am I missing?
Upvotes: 1
Views: 6373
Reputation: 336
Injection is handled by a Java EE Container in execution time. 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. 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.
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.
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(), "[email protected]", "clientId", "clientSecret", true);
userService.createUser(user);
assertTrue(true);
}
}
Upvotes: 2