Introduction to Jukito – Jukito简介

最后修改: 2017年 9月 23日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

Jukito is the combined power of JUnit, Guice, and Mockito – used for simplifying testing of multiple implementations of the same interface.

JukitoJUnitGuiceMockito的综合力量 – 用于简化对同一接口的多种实现的测试。

In this article we’re going to see how authors managed to combine those three libraries to help us reduce a lot of boilerplate code, making our tests flexible and easy.

在这篇文章中,我们将看到作者如何设法结合这三个库来帮助我们减少大量的模板代码,使我们的测试变得灵活和简单。

2. Setting Up

2.设置

First, we’ll add the following dependency to our project:

首先,我们将在我们的项目中添加以下依赖关系。

<dependency>
    <groupId>org.jukito</groupId>
    <artifactId>jukito</artifactId>
    <version>1.5</version>
    <scope>test</scope>
</dependency>

We can find the latest version at Maven Central.

我们可以在Maven中心找到最新版本。

3. Different Implementations of an Interface

3.一个接口的不同实现

To start understanding the power of Jukito, we’re going to define a simple Calculator interface with an Add method:

为了开始了解Jukito的力量,我们将定义一个简单的Calculator 接口,其中有一个Add方法。

public interface Calculator {
    public double add(double a, double b);
}

And we’re going to implement the following interface:

而我们将实现以下接口。

public class SimpleCalculator implements Calculator {

    @Override
    public double add(double a, double b) {
        return a + b;
    }
}

We also need another implementation:

我们还需要另一个实施方案。

public class ScientificCalculator extends SimpleCalculator {
}

Now, let’s use Jukito to test both our implementations:

现在,让我们用Jukito来测试我们的两个实现。

@RunWith(JukitoRunner.class)
public class CalculatorTest {

    public static class Module extends JukitoModule {

        @Override
        protected void configureTest() {
            bindMany(Calculator.class, SimpleCalculator.class, 
              ScientificCalculator.class);
        }
    }

    @Test
    public void givenTwoNumbers_WhenAdd_ThenSumBoth(@All Calculator calc) {
        double result = calc.add(1, 1);
 
        assertEquals(2, result, .1);
    }
}

In this example, we can see a JukitoModule, that wires in all specified implementations.

在这个例子中,我们可以看到一个JukitoModule,它在所有指定的实现中接线。

The @All annotation takes all bindings of the same interface made by the JukitoModule and runs the test with all the different implementations injected at runtime.

@All注解接收由JukitoModule制作的同一接口的所有绑定,并在运行时注入所有不同的实现,运行测试

If we run tests, we can see that indeed two tests are run instead of one:

如果我们运行测试,我们可以看到确实运行了两个测试而不是一个。

Tests run: 2, Failures: 0, Errors: 0, Skipped: 0

4. The Cartesian Product

4.笛卡尔的产品

Let’s now add a simple nested class for different combinations of tests for our Add method:

现在让我们为我们的Add方法的不同组合测试添加一个简单的嵌套类。

public static class AdditionTest {
    int a;
    int b;
    int expected;

    // standard constructors/getters
}

This will expand the number of tests we can run, but first, we need to add additional bindings in our configureTest method:

这将扩大我们可以运行的测试数量,但首先,我们需要在configureTest方法中添加额外的绑定。

bindManyInstances(AdditionTest.class, 
  new AdditionTest(1, 1, 2), 
  new AdditionTest(10, 10, 20), 
  new AdditionTest(18, 24, 42));

And finally we add another test to our suite:

最后,我们将另一个测试添加到我们的套件中。

@Test
public void givenTwoNumbers_WhenAdd_ThenSumBoth(
  @All Calculator calc, 
  @All AdditionTest addTest) {
 
    double result = calc.add(addTest.a, addTest.b);
 
    assertEquals(addTest.expected, result, .1);
}

Now the @All annotation is going to produce the Cartesian product of the different combinations between the different implementations of the Calculator interface and the AdditionTest instances.

现在@All注解将产生Calculator接口的不同实现和AdditionTest实例之间不同组合的笛卡尔乘积。

We can have a look at the increased number of tests it now produces:

我们可以看一下它现在产生的测试数量的增加。

Tests run: 8, Failures: 0, Errors: 0, Skipped: 0

We need to remember that the number of test executions increases drastically for Cartesian products.

我们需要记住,对于笛卡尔产品来说,测试执行的数量急剧增加。

The execution time of all tests will grow linear with the number of executions. i:e.: a test method with three parameters with an @All annotation and four bindings per parameter will be executed 4 x 4 x 4 = 64 times.

所有测试的执行时间将随着执行次数的增加而线性增长。即:一个带有@All注解的三个参数和每个参数有四个绑定的测试方法将被执行4 x 4 x 4 = 64次。

Having five bindings for the same test method will lead to 5 x 5 x 5 = 125 executions.

对同一测试方法有五个绑定,将导致5 x 5 x 5 = 125次执行。

5. Grouping by Names

5.按名称分组

The final feature we’ll discuss is the grouping by name:

我们要讨论的最后一个功能是按名称分组。

bindManyNamedInstances(Integer.class, "even", 2, 4, 6);
bindManyNamedInstances(Integer.class, "odd", 1, 3, 5);

Here, we added some named instances of the integer class to our configureTest method, to showcase what can be done with these groups.

在这里,我们在configureTest方法中添加了一些整数类的命名实例,以展示可以用这些组做什么。

Now let’s add some more tests:

现在让我们再增加一些测试。

@Test
public void givenEvenNumbers_whenPrint_thenOutput(@All("even") Integer i) {
    System.out.println("even " + i);
}

@Test
public void givenOddNumbers_whenPrint_thenOutput(@All("odd") Integer i) {
    System.out.println("odd " + i);
}

The above example will print the six strings “even 2”, “even 4”, “even 6”, “odd 1”, “odd 3”, “odd 5”.

上面的例子将打印 “偶数2″、”偶数4″、”偶数6″、”奇数1″、”奇数3″、”奇数5 “这六个字符串。

Keep in mind that the order of these is not guaranteed at runtime.

请记住,这些的顺序在运行时是不被保证的。

6. Conclusion

6.结论

In this quick tutorial, we took a look at how Jukito allows the use of a whole test suite, by providing just enough combinations of test cases.

在这个快速教程中,我们看了一下Jukito是如何通过提供足够多的测试用例组合而允许使用整个测试套件的。

The complete example can be found over on GitHub.

完整的例子可以在GitHub上找到over