java - 将模拟的多种排列应用于依赖项,以便在 Spring 中进行更好的单元测试

标签 java spring unit-testing mocking

假设我有一个类 (OrchestratingClass),它有一个方法 orchestrate(),该方法调用其他类的许多较小方法(classA 的 do1() 方法, classB 的 do2() 方法)。我想通过使用各种排列模拟 do1()do2() 的响应来测试 orchestrate() 的行为。我正在运行我的测试,例如:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public OrchestratingClassTest {

    @Inject 
    private OrchestratingClass oc;

    @Test 
    public void test1() {
        // I would like to mock classA's do1() method to send back "1"
        // I would like to mock classB's do2() method to send back "2"
    }

    @Test 
    public void test2() {
        // I would like to mock classA's do1() method to send back "100"
        // I would like to mock classB's do2() method to send back "200"
    }

    static class SimpleConfig {

        @Bean
        public InterfaceA interfaceA() {
            return new ClassA();
        }

        @Bean
        public InterfaceB interfaceB() {
            return new ClassB();
        }

        @Bean
        public OrchestratingClass orchestratingClass() {
            return new OrchestratingClass();
        }
    }
}

orchestrationClass 本身非常基本,但我添加了一些示例代码来帮助可视化:

@Named
public OrchestratingClass {

    @Inject
    private InterfaceA interfaceA;

    @Inject
    private InterfaceB interfaceB;

    public String orchestrate() {
        return interfaceA.do1() + " " + interfaceB.do2();
    }
}

现在我知道我可以调整我的 SimpleConfig 类以获得 classA 和 classB 的模拟版本,但随后我被锁定到 1 个特定的模拟中并且无法“重新模拟” “当我进入 test2() 时发生的事情。我确信,如果我们尝试“每次测试”注入(inject)不同“ flavor ”的 bean,那么使用 1 个测试类的 java 配置文件是行不通的。有没有人对我能做些什么有任何建议,以确保我真正彻底地测试这一点而不具有侵入性(例如:为orchestrationClass中的特定类添加多余的“setters”来避免bean注入(inject)的痛苦)?本质上,我希望通过应用各种模拟,在每次测试的基础上针对特定的感兴趣的 bean(以及所需的必要内务处理)“篡改”applicationContext。

最佳答案

这是一个使用 Mockito 的简单示例:

public class OrchestratingClassTest {
    @Mock
    private ClassA mockA;

    @Mock
    private ClassB mockB;

    @InjectMocks
    private OrchestratingClass oc;

    @Before
    public void prepare() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void shouldConcatenate() {
        when(mockA.do1()).thenReturn("1");
        when(mockB.do2()).thenReturn("2");
        assertEquals("1 2", oc.orchestrate());
    }
}

神奇的事情发生在对MockitoAnnotations.initMocks(this)的调用中,它将为用@Mock注释的字段创建模拟实例,然后创建一个真实的实例编排类并注入(inject)其字段,感谢 @InjectMocks

请注意,即使没有这种魔力,您也可以通过添加一个以 ClassA 和 ClassB 作为 OrchestratingClass 参数的构造函数来轻松测试您的类,并使用 @Autowired 注释该构造函数而不是注释字段。因此,简而言之,使用构造函数注入(inject)而不是字段注入(inject)。

关于java - 将模拟的多种排列应用于依赖项,以便在 Spring 中进行更好的单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31509522/

相关文章:

java - Diffie Hellman key agreement 每次JAVA生成不同的key

java - 输入多个数据集(输入)然后打印

java - 嵌套异常是 java.lang.NoClassDefFoundError : Could not initialize class com. my.util.HibernateUtil

java - 在 JAX-WS 中处理异常自定义

javascript - 如何在 mocha 中测试 Uncaught Error ?

使用 Chutzpah 在 Visual Studio 中针对 html 进行 Javascript 单元测试

java - 检查 2 个矩形是否会重叠

java - Java 中的控制台输入

java - 'springSecurityFilterChain' 抛出 java.lang.NullPointerException

c# - 您如何模拟 IAsyncEnumerable?