针对两个不同的注入依赖项运行单元测试

时间:2018-08-21 21:33:59

标签: java spring dependency-injection junit4

我的应用程序中有两个服务bean,它们都实现一个接口。对于该接口,所有方法都必须执行相同的操作(内部原理不同)。

因此,我想编写一套针对两种服务运行的测试。 (不想写重复的代码)

构造测试以完成此任务的最佳方法是什么?

(我已经标记了junit4,因为这是我目前受限的版本。)

4 个答案:

答案 0 :(得分:0)

您可以创建一个包含JavaConfig中的实现列表的bean:

public class TestConfig {

    @Bean
    MyService myService1(){
        return new MyService1();
    }

    @Bean
    MyService myService2(){
        return new MyService2();
    }

    @Bean
    public List<MyService> myServices(MyService myService1, MyService myService2){
        List<MyService> allServices = new ArrayList<>();
        allServices.add(myService1);
        allServices.add(myService2);
        return allServices;
    }
}

并最终在测试中迭代此列表:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=TestConfig.class)
public class ServicesTest {
    @Autowired
    private List<MyService> allServices;
    @Test
    public void testAllServices(){    
        for (MyService service : allServices) {
            // Test service here
        }    
    }
}

答案 1 :(得分:0)

少数选项:

  1. 您可以将所有类存储在类似List<Class<? extends YourInterface>> classes = Arrays.asList(Implementation.class)的常量中,遍历这些类并为每个类调用方法

  2. 您可以使用Reflections查找实现特定接口的所有类,并为每个类循环遍历。

答案 2 :(得分:0)

您可能会自动列出您的服务列表,并按照某些建议进行遍历和测试每个实现。但出于多种原因,我想说这实际上不是一个很好的解决方案:

  • 如果任何一个实现失败,则可能是另一个实现被破坏了,直到修复了该错误之后再次运行测试,您才知道
  • 最好拥有更多非常简单的测试,而不是较少的测试,因为这样做会使查找故障更加困难。
  • 需要Spring-这一点可能无关紧要,但是如果至少要减少正在测试的系统数量,那么不依赖所有这些构造可能是有利的

您可以通过类型参数获得所有花哨的信息,并从带有class BaseTest<HW extends HelloWorldInterface >的通用基类(如@Autowired HW hw继承,然后简单地通过class HelloGermanyTest extends BaseTest<GutenTag>扩展此类,其中GutenTag implements HelloWorldInterface

但是我已经尝试过了,并且发现更简单地针对接口编写断言函数如下:

public static void assertImplementationSaysHelloWorld(HelloWorldInterface hello, String expectedResult) {
    assertEquals(expectedResult, hello);
}

正在进行的事情少得多,并且该函数比继承具有更高的可重用性。例如,如果我有一个实现多个接口的类,则使用继承方法将迫使我编写更多的类来测试每个接口。而我可以在一个测试类中使用任意数量的断言函数。

答案 3 :(得分:0)

这里的其他答案都很好,但并不完全符合我的喜好。 我最终选择了

  • JUnit的@RunWith(@Parameterized)(为两个服务运行测试)
  • Spring的新规则(保留@RunWith(SpringRunner.class)容器,appcontext,webmvc和注入功能)

以下是摘要:

@RunWith(Parameterized.class)

...

@Parameters(name = "Cached = {0}")
public static Boolean[] data() {
    return new Boolean[] { Boolean.TRUE, Boolean.FALSE };
}

@ClassRule
public static final SpringClassRule springClassRule = new SpringClassRule();

@Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();

@Before
public void setUp() {
     // logic to choose the injected service based on the true/false param
}