2

I have a prototype spring bean that has some injected dependencies and also have some constructor arguments.

public BeanA {

  @Inject private BeanB beanB;

  private String arg;

  public BeanA(String arg) {
    this.arg = arg;
  }

public void methodToTest() {
  // ...
  // ...
  // ...
  }

}

I want to unit test this class, mocking my injected BeanB.

Usually, I'd use @InjectMocks to start my mocks inside BeanA.

How can I achieve this? So far, I don't want to inject BeanB in the constructor as it would mix business arguments and dependencies.

fasfsfgs
  • 956
  • 10
  • 16

2 Answers2

1

Why you mix field injection and constructor injection together? I would not recommend field injections at all, especially because they hard to unit test. If you want to mix the injections, maybe this can help:

Spring: unit test for class that has both field & constructor injection

Or you can use reflection to set your mocked BeanB to BeanA

Set private field value with reflection

tomeszmh
  • 218
  • 2
  • 9
  • I'm mixing field injection and constructor injection because my prototype bean stores state (for performance purposes). So my constructor arguments are business related and my field injections wire my dependencies for it to work. Does it make sense? – fasfsfgs Feb 17 '21 at 01:24
  • Nice! I made it work setting private field with ReflectionTestUtils from spring. – fasfsfgs Feb 17 '21 at 01:29
0

Spring has a ReflectionTestUtils that can be used to inject mocks into fields.

@ExtendWith(MockitoExtension.class)
class BeanATest {

  private BeanA beanA;

  @Mock private BeanB beanB;

  void setUp(String arg) {
    beanA = new BeanA(arg);
    ReflectionTestUtils.setField(beanA, "beanB", beanB);
  }

  @Test
  void test() {
    String arg = "arg";
    setUp(arg);

    // ...
    beanA.methodToTest();
    // ...
  }

}

fasfsfgs
  • 956
  • 10
  • 16