【问题标题】:How to mock Spring dependencies in mockito如何在 mockito 中模拟 Spring 依赖项
【发布时间】:2015-12-28 16:26:03
【问题描述】:

我正在尝试模拟 Spring Beans。我能够模拟对象 B 和 C。但无法模拟 B 类中的对象。 插入类 A 的模拟包含 B 。但是 X 和 Y 是空的,即使我已经嘲笑了它们。 Mockito 中是否有任何方法可以模拟 Spring bean 中成员成员的对象。

@Named
@Scope(value = "prototype")
public class A {        
    @Inject
    private B b;
    @Inject
    private C c;        
}

@Named
@Scope(value = "prototype")
public class B {        
    @Inject
    private X x;
    @Inject
    private Y y;        
}

我需要在其中填充 A 类的所有依赖项的测试类。

@RunWith(MockitoJUnitRunner.class)
public class ATest {     

    @InjectMocks
    A a = new A();    

    @Mock
    private B b;
    @Mock
    private C c;

    @Mock
    private X x;
    @Mock
    private Y y;
}

【问题讨论】:

  • 您正在使用 A a = new A(); 创建一个实例;你应该注射它吗?
  • 即使我做@InjectMocks A a,问题仍然存在;
  • A 不依赖于 X 也不依赖于 Y。模拟它们是没有意义的。 B 和 C 是模拟,所以它们也不依赖于 X 和 Y。 X 和 Y 与 A 的检验完全无关。
  • 为什么要模拟 X 和 Y。为什么需要它来测试 A,它只取决于 B 和 C?
  • 这就是为什么你应该模拟 B。一个模拟 B 不使用 X 或 Y。它是一个模拟,即一个完全假的对象,除了你告诉它做的事情之外什么都不做.在发布的代码中,B 被嘲笑。您可以删除无用的 x 和 y 变量。

标签: java spring unit-testing mockito


【解决方案1】:

你可以做下一步。在这种情况下,B 将是间谍对象,因此您可以根据需要在其上模拟方法结果。或者,您可以将真实的 B 方法与模拟的 X 和 Y 方法一起使用。

    @RunWith(MockitoJUnitRunner.class)
public class ATest {        

    @Mock
    private X x;
    @Mock
    private Y y;


        @Spy
        @InjectMocks
        private B b;

        @Mock
        private C c;

        @InjectMocks
        A a; 

        @Before
        public void setUp() {
           MockitoAnnotations.initMock(this);
        }

    }

【讨论】:

  • 这正是我想要的。现在可以在 B 内部设置 X,Y,而 B 又是 A 的成员。
【解决方案2】:

如果你想测试你的班级A,你不需要模拟班级XY。您应该只模拟 BC 类,当然您必须指定模拟对象在调用时返回的内容。

这是一个简单的类的例子。

@Named
@Scope(value = "prototype")
public class A {
    @Inject
    private B b;
    @Inject
    private C c;

    public int someMethod(){
        int value = b.otherMethod();

        return Math.abs(value);
    }
}

@Named
@Scope(value = "prototype")
 class B {
    @Inject
    private X x;
    @Inject
    private Y y;

    public int otherMethod(){
        int value = x.something();
        int otherValuey = y.something();

        return value + otherValuey;
    }
}

你的测试可能看起来像这样。

@RunWith(MockitoJUnitRunner.class)
public class ATest {
    @InjectMocks
    private A a;

    //mock only B and C
    @Mock
    private B b;
    @Mock
    private C c;

    public void shouldTestSomething(){
        //given
        Mockito.when(b.otherMethod()).thenReturn(-1); //you specified what happen when method will invoked

        //when
        int value = a.someMethod();

        //then
        Assert.assertEquals(1, value);
    }
}

【讨论】:

    【解决方案3】:

    您可以将Springs test runner 与测试应用程序上下文xml 一起使用。

    在这个测试应用程序上下文中,您可以使用 Mockito 类上的 springs 工厂方法属性简单地创建任何模拟:

    <bean id="mockBean" class="org.mockito.Mockito" factory-method="mock"> 
        <constructor-arg value="com.package.ClassToBeMocked" /> 
    </bean>
    

    然后你可以将这个 mockBean 注入到你的另一个 bean 中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多