【问题标题】:How to mock behavior for Springockito mocks?如何模拟 Springockito 模拟的行为?
【发布时间】:2012-06-21 02:44:13
【问题描述】:

如果我按照here 的描述使用 Springockito 在我的 spring 上下文文件中创建一个模拟,我该如何模拟它的一些行为?

我正在尝试做的事情:

  1. A 类正在测试中。
  2. ClassB 在 ClassA 中自动装配。
  3. ClassB 正在使用 Springockito 进行模拟。
  4. ClassA 需要 ClassB 在其 PostConstruct 中做某事。
  5. 我需要模拟 ClassB 来做这件事,因为它不能也不应该真的这样做。

无需使用 Springockito(直接使用 Mockito)即可直接执行此操作,但我需要自动装配这些 bean 并在我的测试中使用 Spring。任何帮助表示赞赏。

【问题讨论】:

    标签: java spring mocking mockito springmockito


    【解决方案1】:

    请注意,新的springockito-annotations 有助于实现相同的目标,而不会弄乱 xml 上下文和额外的辅助类:

    @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
        }
    
    }
    

    这将导致 ClassB 在主应用程序上下文初始化时被替换为模拟。

    【讨论】:

    • 你能分享一下 test-config.xml 吗?
    【解决方案2】:

    我不熟悉 Springockito,但它对于一些狭窄的案例看起来很有趣 - 即带有一点模拟的集成测试。

    无论如何,对于您扩展 AbstractJUnit4SpringContextTests 的简单用例,您也可以像在 ClassA 中一样在测试中自动装配 ClassB。然后,您可以在 setup 方法中定义 ClassB 的预期行为。

    但我认为您需要先为 ClassB bean 设置一些行为,然后才能在 setup 方法中访问它。在这种情况下,您可能需要另一个 bean 来设置 ClassB 以执行预期的行为。所以你的 testContext.xml 里面会有这样的东西:

    <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>
    

    ClassBMockSetter 看起来像:

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

    我认为这可行,但到那时,手动编写模拟 ClassB 不是更容易吗?

    【讨论】:

    • 谢谢,这正是我想要的。当您说手动编写模拟代码时,代码将存在于何处,因为它需要在 ClassATest 中实例化 ClassA 时以及在调用 post 构造方法之前。
    【解决方案3】:

    对我有用的是使用 @InjectMocks 表示法。 (见https://bitbucket.org/kubek2k/springockito/wiki/Home

    @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(loader = SpringockitoContextLoader.class,位置 = "classpath:test-config.xml") @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) 公共类 MemoAutoTest 扩展 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();
    }
    

    }

    【讨论】:

      猜你喜欢
      • 2015-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-28
      • 2020-05-21
      • 2012-05-28
      相关资源
      最近更新 更多