Mocking EJB injection in tests - java

Whenever I want to test a class which uses resource injection I end up including a constructor that will only be used within the test:
public class A {
#EJB
B b;
// Used in tests to inject EJB mock
protected A(B b) {
this.b = b;
}
public A() {}
// Method that I wish to test
public void foo() {
b.bar();
}
}
Is there another way of mocking resource injection or this is the correct pattern to follow?

you could use easy gloss to that effect, it mocks the EJBs injection system.
another way is to set the field using reflexion in your tests, I sometime use something like this :
public static void setPrivateField(Class<? extends Object> instanceFieldClass, Object instance, String fieldName, Object fieldValue) throws Exception {
Field setId = instanceFieldClass.getDeclaredField(fieldName);
setId.setAccessible(true);
setId.set(instance, fieldValue);
}

Eliocs,
If type B where an interface then you wouldn't "just" bo doing it for test-cases; you'd be allowing for any alternative implementations of "B's behaviour", even if the need for it/them hasn't been dreamed-up yet.
Yeah, basically that's the only pattern to follow (AFAIK)... so (rightly or wrongly) you may as well make the best of it ;-)
Cheers. Keith.

It's certainly one way to do it, although I'd rely on package access; don't provide a constructor injection point, but simply have your test in the same package as the bean being tested. That way, your test can just access the value directly (assuming it's not private):
#Test
public void EJBInjectionTest() {
A a=new A();
a.b=new B() {
// mock functionality here, of course...
};
assertNotNull(a.b);
}

According to this article (Mockito and Dependency Injection), Mockito has support for injecting mocked resources.
public class ATest
{
#InjectMocks
private A a; //this is your class under test into which the mocks will be injected.
#Mock
private B b; //this is the EJB to be injected.
#Before
public void setUp()
{
MockitoAnnotations.initMocks(this);
}
}
You can also inject multiple mocks. Just declare them in the same way as we did for B b.
The initMocks part can also be done in each test or in a BeforeClass setup method depending on your needs.

Related

How to mock classes with constructor injection

How to get constructor injection in Mockito
I have the following class:
class A {
private B mB;
A(B b) {
mB = b;
}
void String someMethod() {
mB.execute();
}
}
how do I test someMethod using a mock class A and class B using
B b = Mockito.mock(B.class)
Mockito.when(b.execute()).thenReturn("String")
A a = Mockito.mock(A.class)
//somehow inject b into A and make the below statement run
Mockito.when(a.someMethod()).check(equals("String"))
You need create real A class because you want to test it but you need to mock other classes used in A class. Also, you can find mockito documentation says that don't mock everything.
class ATest {
#Mock
private B b;
private A a;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
a = new A(b);
}
#Test
public String someMethodTest() {
String result = "result";
Mockito.when(b.execute()).thenReturn(result);
String response = a.someMethod();
Mockito.verify(b, Mockito.atLeastOnce()).execute();
assertEquals(response, result);
}
}
Another way of injecting a mock to real object (as A should be a real object) is to use annotations, they will create objects you want:
#Mock
B mockOfB;
#InjectMocks
A realObjectA;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
Then, like they said, run the method you want to test without mockito (because you want to test it, so call it on real instance) and check the result according to your expectations.
Behaviour of object B can be mocked in any way, to satisfy your needs.
You want to test someMethod() of class A. Testing the execute() of class B should take place in the other test, because instance of B is a dependency in your case. Test for execute() should be made in different test.
You don't need to test how B object will behave, so you need to mock it and afterwards, check that execute() was invoked.
So in your case your test will look something like this:
B b = Mockito.mock(B.class);
A a = new A( b );
a.someMethod();
Mockito.verify( b, Mockito.times( 1 ) ).execute();
In my opinion, you're mixing up two ways of testing.
If you want to write a test using Mockito, you just create a mock of some class and use it. This mock doesn't have anything related to a real object as you can (should) mock every method that is called in the test. That's why it doesn't make any sense to mock class B - it is simply not used by class A.
Otherwise, if you want to test a real behavior of class A then why do you want to mock it? Create a real instance of class A with a mocked instance of class B.
That's it! Don't mix it up.

Mocking autowired field in the method

I was wondering whether there's a way to mock the field which is being autowired.
Consider the following case.
I have a class name A
public class A {
#Autowired
private B b;
public void aMethod() {
b.method();
}
}
The other class B looks like this
public class B {
public void method() {
// some code
}
}
Now i want to write junit for the method.
I know there's a way to mock the autowired field like this.
public class TestA {
#InjectMock
private A a;
#Mock
private B b;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
public void testAMethod() {
// write test case.
}
}
But my question is -> Is there a way to mock the autowired field inside method after creating object with new.
eg
public class TestA {
public void testAMethod() {
A a =new A();
// how to mock the B instance in it.
}
}
Please suggest or there's no way to do this????
I dont want to change from private modifier. Nor i want to add getter's and setters or reflection. I just want to know is there a way to mock the B instance after creating the new object of A class.
How about ReflectionTestUtils?
A a = new A();
B b = mock(B.class);
ReflectionTestUtils.setField(a, "b", b);
It's still reflection-based and has all related drawbacks, though it's quite simple and easy to read.
You can not do that with mockito, this would require to modify the bytecode of the class being tested. However Powermock allows such stubs. Note though that I and the creator of Powermock - Johan Haleby - would push for a refactoring instead of using Powermock. Powermock is very powerful, maybe too much, and working allows anyone to write legacy code, that would be difficultly maintainable or extensible (property you can find in poorly designed legacy code).
In your case I don't know what's wrong in your case with the dependency injection. However if the code need a new instance of B, it may be useful to have inject in A a factory/provider/builder class which will make a new instance of B. Such code can be easily stubbed with Mockito.

Does Guice support a way of method injection (non setter injection)?

From what I understand Guice supports injection for: Constructors, Setters (which they call method injection for some reason), fields.
Can it also inject method parameters? For example:
void foo(InterfaceA a, InterfaceA a1){
...
}
interface InterfaceA{
...
}
class A implements InterfaceA{
....
}
class B implements InterfaceA{
....
}
I want to be able to bind a in foo to type A and a1 to B (will probably need annotation but lets ignore that for a second).
I want this to be done on invocation.
This seems different from the normal use cases (c'tor, fields, setters) in the sense that the dependency injection will happen on invocation rather than on object creation.
So is this possible?
Vladimir's answer is correct, but rather than injecting the injector, you can use field injection and Providers to do the same more concisely and to check that dependencies are satisfied at injector creation time. This code is the same as his, but modified to use Providers:
Injector injector = Guice.createInjector(b -> {
b.bind(InterfaceA.class).annotatedWith(Names.named("a")).to(A.class);
b.bind(InterfaceA.class).annotatedWith(Names.named("a1")).to(B.class);
b.bind(Invoke.class);
});
public class Invoke {
// Constructor injection works too, of course. These fields could also be
// made private, but this could make things difficult to test.
#Inject #Named("a") Provider<InterfaceA> aProvider;
#Inject #Named("a1") Provider<InterfaceA> a1Provider;
public void invoke() {
this.foo(aProvider.get(), a1Provider.get());
}
void foo(InterfaceA a, InterfaceA a1){
...
}
}
Well, you can do this:
Injector injector = Guice.createInjector(b -> {
b.bind(InterfaceA.class).annotatedWith(Names.named("a")).to(A.class);
b.bind(InterfaceA.class).annotatedWith(Names.named("a1")).to(B.class);
b.bind(Invoke.class);
});
public class Invoke {
private final Injector injector;
#Inject
Invoke(Injector injector) {
this.injector = injector;
}
public void invoke() {
this.foo(
injector.getInstance(Key.get(InterfaceA.class, Names.named("a"))),
injector.getInstance(Key.get(InterfaceA.class, Names.named("a1")))
);
}
void foo(InterfaceA a, InterfaceA a1){
...
}
}
But nothing more. Guice is a dependency injection framework and it usually means "construct objects with all their dependencies". While method parameters are dependencies formally (since the class is supposed to use them - this is the definition of dependency), they are not usually regarded as those by DI frameworks. It is understandable - this would make these frameworks much more complex for little to no gain, and also Java is not expressive enough language for such things not to look obscenely ugly.

Java: How do I mock a method of a field when that field isn't exposed?

I'm using Java 6, JUnit 4.8.1, and writing a console application. My application has a member field that isn't exposed …
public class MyApp {
...
private OpportunitiesService m_oppsSvc;
private void initServices() {
…
m_oppsSvc = new OpportunitiesServiceImpl(…);
}
...
}
I want to mock a behavior such that whenever one method from my service is called, (e.g. m_oppsSvc.getResults()), the same result is always returned. How do I do that? There's no setter method for the field. I'm currently working with Mockito 1.8.4. Is it possible to do this with Mockito or some other mock framework?
This is what you want:
#RunWith(MockitoJUnitRunner.class)
public class MyAppTest {
#Mock private OpportunitiesService mocked_m_oppsSvc;
#InjectMocks MyApp myApp;
#Test public void when_MyApp_uses_OpportunititesService_then_verify_something() {
// given
given( mocked_m_oppsSvc.whatever()).willReturn(...);
// when
myApp.isUsingTheOpportunitiesService(...);
// then
verify...
assertThat...
}
}
Using: Mockito 1.9.0, BDD style, FEST-Assert AssertJ.
Hope that helps :)
Given that you're already using mockito, why not just use reflection:
#RunWith(MockitoJUnitRunner.class)
public class MyApp {
#Mock
private OpportunitiesService m_oppsSvc;
private MyApp myApp;
#Before
public void before() throws Exception {
myApp = new MyApp();
Field f = MyApp.class.getDeclaredField("m_oppsSvc");
f.setAccessible(true);
f.set(myApp, m_oppsSvc);
}
}
It's a bit ugly, but it will do the trick. Note that this may not be the most efficient way to do it with Mockito, but it will work.
There's also Powermock which should allow you to do this as well using the Whitebox class. I won't get into the whole details of Powermock but here's the call to inject the private field value, which should be a mock object:
Whitebox.setInternalState(myApp, "m_oppsSvc", m_oppsSvc);
You should consider attempts to mock a private field a smell. That is, a sign that either what you're trying to do is either incorrect or that your code is currently structured incorrectly. You should only need to mock public methods or injected dependencies
In the code you've given you should consider injecting OpportunitiesService as follows:
public class MyApp {
...
private OpportunitiesService m_oppsSvc;
public MyApp(OpportunitiesService oppsSvc) {
this.m_oppsSvc = oppsSvc;
}
...
}
In your test you can then inject a mock as follows:
OpportunitiesService mockOpportunitiesService =
Mockito.mock(OpportunitiesService.class);
Mockit.when(mockOpportunitiesService.someMethod()).thenReturn(someValue);
MyApp app = new MyApp(mockOpportunitiesService);
You can easily do it with JMockit:
public class MyAppTest
{
#Tested MyApp myApp;
#Test
public testSomething(final #Capturing OpportunitiesService mockService)
{
new NonStrictExpectations() {{
mockService.getResults(); result = asList("a", "b", "C");
// record other expectations, if needed
}};
myApp.whateverMethodIWantToTest();
new Verifications() {{
mockService.doSomething(anyInt);
// verify other expectations, if needed
}};
}
}
Even though the implementation class OpportunitiesServiceImpl isn't mentioned in test code, its instances (any number of them) will still get properly mocked.
Generally you should use dependency injection and pass the mock object (of type OppportunitiesServiceImpl) in via the constructor, a separate setter or directly to the method (getResults). You might need to extract an interface for OpportunitiesServiceImpl first.
Usually, this is solved through the use of dependency injection. In regular (production) mode, your dependency injection container (e.g. Spring or Guice) will inject an instance of OpportunitiesService into MyApp through your constructor or through a setter.
Then, when you're testing you can "inject" a mock instance manually using the same setter or constructor argument.
Instead of doing
m_oppsSvc = new OpportunitiesServiceImpl(…);
Try Passing OpportunitesService in through MyApp's constructor

Mockito, Testing an object that relies on injected dependencies (Spring)?

I'm new to using Mockito and am trying to understand a way to make a unit test of a class that relies on injected dependencies. What I want to do is to create mock objects of the dependencies and make the class that I am testing use those instead of the regular injected dependencies that would be injected by Spring. I have been reading tutorials but am a bit confused on how to do this.
I have one the class I want to test like this:
package org.rd.server.beans;
import org.springframework.beans.factory.annotation.Autowired;
public class TestBean1 {
#Autowired
private SubBean1 subBean1;
private String helloString;
public String testReturn () {
subBean1.setSomething("its working");
String something = subBean1.getSomething();
helloString = "Hello...... " + something;
return helloString;
}
Then I have the class that I want to use as a mock object (rather than the regular SubBean1 class, like below:
package org.rd.server.beans.mock;
public class SubBean1Mock {
private String something;
public String getSomething() {
return something;
}
public void setSomething(String something) {
this.something = something;
}
}
}
I just want to try running a simple test like this:
package test.rd.beans;
import org.rd.server.beans.TestBean1;
import junit.framework.*;
public class TestBean1Test extends TestCase
{
private TestBean1 testBean1;
public TestBean1Test(String name)
{
super(name);
}
public void setUp()
{
testBean1 = new TestBean1();
// Somehow inject the mock dependency SubBean1Mock ???
}
public void test1() {
assertEquals(testBean1.testReturn(),"working");
}
}
I figure there must be some fairly simple way to do this but I can't seem to understand the tutorials as I don't have the context yet to understand everything they are doing / explaining. If anyone could shed some light on this I would appreciate it.
If you're using Mockito you create mocks by calling Mockito's static mock method. You can then just pass in the mock to the class you're trying to test. Your setup method would look something like this:
testBean1 = new TestBean1();
SubBean1 subBeanMock = mock(SubBean1.class);
testBean1.setSubBean(subBeanMock);
You can then add the appropriate behavior to your mock objects for whatever you're trying to test with Mockito's static when method, for example:
when(subBeanMock.getSomething()).thenReturn("its working");
In Mockito you aren't really going to create new "mock" implementations, but rather you are going to mock out the methods on the interface of the injected dependency by telling Mockito what to return when the method is called.
I wrote a test of a Spring MVC Controller using Mockito and treated it just like any other java class. I was able to mock out the various other Spring beans I had and inject those using Spring's ReflectionTestUtils to pass in the Mockito based values. I wrote about it in my blog back in February. It has the full source for the test class and most of the source from the controller, so it's probably too long to put the contents here.
http://digitaljoel.nerd-herders.com/2011/02/05/mock-testing-spring-mvc-controller/
I stumbled on this thread while trying to set up some mocks for a slightly more complicated situation and figured I'd share my results for posterity.
My situation was similar in the fact that I needed to mock dependencies, but I also wanted to mock some of the methods on the class I was testing. This was the solution:
#MockBean
DependentService mockDependentService
ControllerToTest controllerToTest
#BeforeEach
public void setup() {
mockDependentService = mock(DependentService.class);
controllerToTest = mock(ControllerToTest.class);
ReflectionTestUtils.setField(controllerToTest, "dependantService", mockDependentService);
}
#Test
void test() {
//set up test and other mocks
//be sure to implement the below code that will call the real method that you are wanting to test
when(controllerToTest.methodToTest()).thenCallRealMethod();
//assertions
}
Note that "dependantService" needs to match whatever you have named the instance of the service on your controller. If that doesn't match the reflection will not find it and inject the mock for you.
This approach allows all the methods on the controller to be mocked by default, then you can specifically call out which method you want to use the real one. Then use the reflection to set any dependencies needed with the respective mock objects.
Hope this helps someone down the road as it stumped me for a while.

Categories

Resources