5

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?

eliocs
  • 18,511
  • 7
  • 40
  • 52

4 Answers4

1

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);
}
user691154
  • 192
  • 2
  • 9
  • Something like easy gloss was what I was looking for, thank you! – eliocs Apr 28 '11 at 19:40
  • Using reflection is problematic since an EJB reference is actually a reference to a stub object in the EJB container (pointing to an EJB), you cannot examine the actual EJB itself. – Bartek Maraszek Dec 02 '14 at 14:18
0

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.

  • The article mentions only Spring Autowired and JSR330 Inject annotations. It does not mention EJB annotation which is exactly what was being asked. I've just tested this setup with Mockito v3.11.1 and quite unsurprisingly it does NOT work. Resisted the urge to downvote anyways. – Jacek Prucia Jun 16 '21 at 15:26
0

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.

corlettk
  • 13,288
  • 7
  • 38
  • 52
0

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);
}
Joseph Ottinger
  • 4,911
  • 1
  • 22
  • 23
  • 1
    I like this way because there is no need to add additional lines of code. Thanks! – eliocs Apr 25 '11 at 14:24
  • HI.. is it possible if B is interface. please suggest also how can we mock object – Dhrumil Shah Nov 04 '16 at 05:34
  • I have created a new Object with one implemented class. Object value is present while running in Test cases class but its not available at actual class. Can you please suggest it. – Dhrumil Shah Nov 04 '16 at 05:41