简体   繁体   中英

How to mock behavior for Springockito mocks?

If I create a mock in my spring context file using Springockito as described here , how do I mock some behavior for it?

What I'm trying to do:

  1. ClassA is being tested.
  2. ClassB is autowired in ClassA.
  3. ClassB is being mocked with Springockito.
  4. ClassA needs ClassB to do something in its PostConstruct.
  5. I need to mock ClassB to do that something, since it can't and shouldn't really do it.

Doing this is straight forward without using Springockito (using Mockito straight up), but I need to autowire these beans and use Spring in my tests. Any help is appreciated.

Note that new springockito-annotations help to achieve the same goal without messing with xml context and extra helper classes:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = SpringockitoContextLoader.class, locations = "classpath:test-config.xml")
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class MemoAutoTest extends AbstractJUnit4SpringContextTests {

    @Autowired
    private ClassA classA;
    @Autowired @ReplaceWithMock
    private ClassB classB;

    @Test
    public void testClassA() {
        // stub B 
        when(classB.foo()).thenReturn(true);
        when(classB.bar()).thenReturn(42);

        // test A
    }

}

This would cause ClassB to be replaced with mock at main application context initialization.

I'm not familiar with Springockito, but it looks interesting for some narrow cases - namely integration testing with mocking just a bit.

Anyway, it looks like for a straightforward use case you extend AbstractJUnit4SpringContextTests , you could also autowire ClassB in your test just like you do in ClassA. Then you could define your expected behavior for ClassB in your setup method.

But I think that you need to set up some behavior for the ClassB bean before you get access to it in your setup method. In that case, you may need another bean to set up ClassB to do the expected behavior. So your testContext.xml would have something like this in it:

<bean id="classA" class="com.jarvis.ClassA" depends-on="classBMockSetter" />
<mockito:mock id="classB" class="com.jarvis.ClassB" />
<bean id="classBMockSetter" class="com.jarvis.test.ClassBMockSetter">
  <property name="classB" ref="classB" />
</bean>

The ClassBMockSetter would look something like:

public class ClassBMockSetter {
  private ClassB classB;
  public void setClassB(ClassB classB) {
    this.classB = classB;
    given(classB.foo()).willReturn(true);
    given(classB.bar()).willReturn(42);
  }
}

I think that would work, but at that point, isn't it easier to just hand-code your mock ClassB?

What is worked for me is using @InjectMocks notation. (See https://bitbucket.org/kubek2k/springockito/wiki/Home )

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(loader = SpringockitoContextLoader.class, locations = "classpath:test-config.xml") @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) public class MemoAutoTest extends AbstractJUnit4SpringContextTests {

@Autowired
private ClassA classA;
@Autowired @InjectMocks
private ClassB classB;

@Test
public void testClassA() {
    // stub B 
    when(classB.foo()).thenReturn(true);
    when(classB.bar()).thenReturn(42);

    // test A
    classA.doSomethingThatInternallyCallClassBFoo();
}

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM