Schlagwort-Archive: mockito

Mocking SessionContext

I have a EJB:

@Stateless
@Remote
public class ejbBean implements EjbBean {
	@PersistenceContext
	private EntityManager em;
	@Resource
	private SessionContext ctx;
 
	public String someMethod() {
		String name = ctx.getCallerPrincipal().getName();
		return name;
	}
}
public class EjbBeanTest {
	@Rule
	public final MockitoRule mockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
	@Mock
	private EntityManager em;
	@Mock
	private SessionContext ctx;
 
	@InjectMocks
	private EjbBean cut;
 
	@Before
	public void setUp() {
		Principal p = mock(Principal.class);
		when(ctx.getCallerPrincipal()).thenReturn(p);
		when(p.getName()).thenReturn("TestUser");
	}
 
	@Test
	public void test() {
		String result = cut.someMethod();
		assertEquals("TestUser", result);
	}

causes the following exception

org.mockito.exceptions.base.MockitoException: 
Mockito cannot mock this class: interface javax.ejb.SessionContext.

Mockito can only mock non-private & non-final classes.

I made lot of searches over the web. (google, stackOverflow, git, everywhere)
I found some suggestions like https://stackoverflow.com/questions/32695925/how-do-i-mock-a-sessioncontext-injected-via-resource-in-java-ee.
I tried everything.
But what ever I tried I got failing test with the Error message above.
WTF.
My friend give me the tip … Don`t use an mocking framework, make your own dummy.
OK lets try this. Fill the one method I need then instantiate this.

public class DummySessionContext implements SessionContext {
...
	@Override
	public Principal getCallerPrincipal() {
		// TODO Auto-generated method stub
		Principal principal = () -> "TESTUSER";
		return principal;
	}
...	
}

And this brings a new Error up.

java.lang.Error: Unresolved compilation problems: 
	The type javax.xml.rpc.handler.MessageContext cannot be resolved. It is indirectly referenced from required .class files
	MessageContext cannot be resolved to a type

It turns out that there was a missing dependency in pom.
Because we have scope = provide

<dependency>
	<groupId>org.jboss.spec.javax.ejb</groupId>
	<artifactId>jboss-ejb-api_3.2_spec</artifactId>
	<scope>provided</scope>
</dependency>

my mentor said

provided -> means provided by ejb container
provided dependencies will NOT be there for tests
I think you have to create dependency with test

I added the following to my pom

<!-- needed SessionContext mock-->
<dependency>
	<groupId>org.jboss.spec.javax.xml.rpc</groupId>
	<artifactId>jboss-jaxrpc-api_1.1_spec</artifactId>
	<version>1.0.1.Final</version>
	<scope>test</scope>
</dependency>

Now the test works fine.
With my own dummy.
EJB:

@Stateless
@Remote
public class ejbBean implements EjbBean {
	@PersistenceContext
	private EntityManager em;
	private SessionContext ctx;
 
	@Resource
	void setSessionContext(SessionContext ctx) {
		this.ctx = ctx;
	}
 
	public String someMethod() {
		String name = ctx.getCallerPrincipal().getName();
		return name;
	}
}

Dummy:

public class DummySessionContext implements SessionContext {
...
	@Override
	public Principal getCallerPrincipal() {
		// TODO Auto-generated method stub
		Principal principal = () -> "TESTUSER";
		return principal;
	}
...	
}

TEST:

public class EjbBeanTest {
	@Rule
	public final MockitoRule mockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
	@Mock
	private EntityManager em;
 
 
	@InjectMocks
	private EjbBean cut;
 
	@Before
	public void setUp() {
		cut.setSessionContext(new DummySessionContext());
	}
 
	@Test
	public void test() {
		String result = cut.someMethod();
		assertEquals("TestUser", result);
	}
}

Furthermore I tried to mock again.
And now this works too.

EJB:

@Stateless
@Remote
public class ejbBean implements EjbBean {
	@PersistenceContext
	private EntityManager em;
	@Resource
	private SessionContext ctx;
 
	public String someMethod() {
		String name = ctx.getCallerPrincipal().getName();
		return name;
	}
}

TEST:

public class EjbBeanTest {
	@Rule
	public final MockitoRule mockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
	@Mock
	private EntityManager em;
	@Mock
	private SessionContext ctx;
 
	@InjectMocks
	private EjbBean cut;
 
 
	@Test
	public void test() { 
		Principal p = mock(Principal.class);
		when(ctx.getCallerPrincipal()).thenReturn(p);
		when(p.getName()).thenReturn("TestUser");
 
		String result = cut.someMethod();
		assertEquals("TestUser", result);
	}
}

Conclusion
I my case using the mockito hides the missing dependency. And I had a hard time to figure it out.
Many thanks to my friend and Sensai Jiri.