Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在生产中使用CDI测试类时注入模拟_Java_Unit Testing_Mockito_Cdi - Fatal编程技术网

Java 如何在生产中使用CDI测试类时注入模拟

Java 如何在生产中使用CDI测试类时注入模拟,java,unit-testing,mockito,cdi,Java,Unit Testing,Mockito,Cdi,我在JavaSE环境中使用WELD-SE进行依赖注入编程。因此,类的依赖项如下所示: public class ProductionCodeClass { @Inject private DependencyClass dependency; } 在为此类编写单元测试时,我正在为DependencyClass创建一个模拟,因为我不想为我运行的每个测试启动一个完整的CDI环境,所以我手动“注入”模拟: import static TestSupport.setField; imp

我在JavaSE环境中使用WELD-SE进行依赖注入编程。因此,类的依赖项如下所示:

public class ProductionCodeClass {
    @Inject
    private DependencyClass dependency;
}
在为此类编写单元测试时,我正在为
DependencyClass
创建一个模拟,因为我不想为我运行的每个测试启动一个完整的CDI环境,所以我手动“注入”模拟:

import static TestSupport.setField;
import static org.mockito.Mockito.*;

public class ProductionCodeClassTest {
    @Before
    public void setUp() {
        mockedDependency = mock(DependencyClass.class);
        testedInstance = new ProductionCodeClass();
        setField(testedInstance, "dependency", mockedDependency);
    }
}
静态导入的方法
setField()
我使用测试中使用的工具在一个类中编写了自己:

public class TestSupport {
    public static void setField(
                                final Object instance,
                                final String field,
                                final Object value) {
        try {
            for (Class classIterator = instance.getClass();
                 classIterator != null;
                 classIterator = classIterator.getSuperclass()) {
                try {
                    final Field declaredField =
                                classIterator.getDeclaredField(field);
                    declaredField.setAccessible(true);
                    declaredField.set(instance, value);
                    return;
                } catch (final NoSuchFieldException nsfe) {
                    // ignored, we'll try the parent
                }
            }

            throw new NoSuchFieldException(
                      String.format(
                          "Field '%s' not found in %s",
                          field,
                          instance));
        } catch (final RuntimeException re) {
            throw re;
        } catch (final Exception ex) {
            throw new RuntimeException(ex);
        }
    }
}
我不喜欢这个解决方案的地方是,在任何新项目中,我都需要这个助手。我已经将它打包为一个Maven项目,我可以将它作为测试依赖项添加到我的项目中


但是,在其他一些公共图书馆里,难道没有我错过的现成的东西吗?对我的一般做法有何评论?

Mockito支持开箱即用:

public class ProductionCodeClassTest {

    @Mock
    private DependencyClass dependency;

    @InjectMocks
    private ProductionCodeClass testedInstance;

    @Before
    public void setUp() {
        testedInstance = new ProductionCodeClass();
        MockitoAnnotations.initMocks(this);
    }

}
注释将触发测试类中模拟的类或接口的注入,在本例中为
DependencyClass

Mockito尝试按类型注入(在类型相同的情况下使用名称)。Mockito在注入失败时不会抛出任何东西-您必须手动满足依赖项

在这里,我还使用了
@Mock
注释,而不是调用
Mock()
。您仍然可以使用
mock()
,但我更喜欢使用注释

另外,还有一些反射工具可用,它们支持您在
TestSupport
中实现的功能。一个这样的例子是


也许更好的方法是使用:

这里的主要优点是,很清楚类依赖于什么类,并且如果不提供所有依赖项,就很难构建它。此外,它允许注入的类是final

通过这样做,
@InjectMocks
是不必要的。相反,只需通过将mock作为参数提供给构造函数来创建类:

public class ProductionCodeClassTest {

    @Mock
    private DependencyClass dependency;

    private ProductionCodeClass testedInstance;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        testedInstance = new ProductionCodeClass(dependency);
    }

}

当mockitos内置函数不满足要求时的备选方案:尝试

它是一个注入/模拟框架,允许注入模拟和具体实例,还支持生命周期模拟的后构造

 public class ProductionCodeClassTest {

    @Rule
    public final NeedleRule needle = new NeedleRule();

    // will create productionCodeClass and inject mocks by default
    @ObjectUnderTest(postConstruct=true)
    private ProductionCodeClass testedInstance;

    // this will automatically be a mock
    @Inject
    private AServiceProductionCodeClassDependsOn serviceMock;

    // this will be injected into ObjectUnderTest 
    @InjectIntoMany
    private ThisIsAnotherDependencyOfProdcutionCodeClass realObject = new ThisIsAnotherDependencyOfProdcutionCodeClass ();

    @Test
    public void test_stuff() {
         ....
    }

}

是的,这就是我锁定的原因。已经试过了,效果很好。我找不到这个…;-)我没有使用Spring,所以仅仅添加它来获取ReflectionTestUtils可能有点重。但无论如何也要感谢您的建议。@Magnilex:您是否考虑过将
@RunWith(MockitoJUnitRunner.class)
@Rule public MockitoRule Rule…
添加到您的代码中以使其完整?@Henrik代码已完成<代码>@RunWith(MockitoJUnitRunner.class)将是另一种选择。然而,这个答案解释了OP:s的问题,这个问题并不是询问如何运行基于mockito的JUnit测试。@Magnilex:Ah,好的。我认为Mockito必须被更明确地调用。谢谢回复。使用构造函数注入。很好!是否有一个示例项目/测试套件?类似于JMockit的sample()的东西是理想的。但这可能会有所帮助:
 public class ProductionCodeClassTest {

    @Rule
    public final NeedleRule needle = new NeedleRule();

    // will create productionCodeClass and inject mocks by default
    @ObjectUnderTest(postConstruct=true)
    private ProductionCodeClass testedInstance;

    // this will automatically be a mock
    @Inject
    private AServiceProductionCodeClassDependsOn serviceMock;

    // this will be injected into ObjectUnderTest 
    @InjectIntoMany
    private ThisIsAnotherDependencyOfProdcutionCodeClass realObject = new ThisIsAnotherDependencyOfProdcutionCodeClass ();

    @Test
    public void test_stuff() {
         ....
    }

}