如何将@InjectMocks与参数化测试一起使用

3phpmpom  于 2022-11-08  发布在  其他
关注(0)|答案(2)|浏览(126)

Note: I have done a search and read various blogs, but cannot find an example that matches what I am trying to do.
I have a ConverterService which uses a CodeService that is injected into it. I am attempting to write a JUnit test in which I mock the CodeService and inject that mock into the ConverterService under test. The test is Parameterized.
Consider the following code:

@RunWith(Parameterized.class)
public class ConverterServiceTest {

    @Parameters(name="{index}; Test case {0}")
    public static Collection<Object[]> initTestCases() {
        final Object[][] testCases = {
                { "One",   "First",   TypeEnum.ONE   },
                { "Two",   "Second",  TypeEnum.TWO   },
                { "Three", "Third",   TypeEnum.THREE },
                { "Four",  "Fourth",  TypeEnum.FOUR  },
                { "Five",  "Fifth",   TypeEnum.FIVE  },
                { "Six",   "Unknown", TypeEnum.BLANK }
        };
        return Arrays.asList(testCases);
    }

    @Parameter(0) private String   testName;
    @Parameter(1) private String   testCode;
    @Parameter(2) private TypeEnum expectedCode;

    @Rule public ExpectedException expected = ExpectedException.none();
    @Mock private CodeService codeService;
    @InjectMocks private ConverterService converter;

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

        when(codeService.isOne(anyString())).thenReturn(false);
        when(codeService.isOne("First")).thenReturn(true);

        when(codeService.isTwo(anyString())).thenReturn(false);
        when(codeService.isTwo("Second")).thenReturn(true);

        when(codeService.isThree(anyString())).thenReturn(false);
        when(codeService.isThree("Third")).thenReturn(true);

        when(codeService.isFour(anyString())).thenReturn(false);
        when(codeService.isFour("Fourth")).thenReturn(true);

        when(codeService.isFive(anyString())).thenReturn(false);
        when(codeService.isFive("Fifth")).thenReturn(true);
    }

    @Test public void testCodeConverter() {
        assertThat(converter.convert(testCode), equalTo(expectedCode));
    }
}

I am using the Parameterized.class runner, I am using MockitoAnnotations.initMocks(this), my @Before is initialising the mock CodeService, but I am not getting injection into ConverterService. In fact I am getting some strange reflection errors:
java.lang.IllegalAccessException: Class org.junit.runners.parameterized.BlockJUnit4ClassRunnerWithParameters can not access a member of class com.company.converter.ConverterServiceTest with modifiers "private" at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102) at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296) at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288) at java.lang.reflect.Field.set(Field.java:761) at org.junit.runners.parameterized.BlockJUnit4ClassRunnerWithParameters.createTestUsingFieldInjection(BlockJUnit4ClassRunnerWithParameters.java:62) at org.junit.runners.parameterized.BlockJUnit4ClassRunnerWithParameters.createTest(BlockJUnit4ClassRunnerWithParameters.java:36) at org.junit.runners.BlockJUnit4ClassRunner$1.runReflectiveCall(BlockJUnit4ClassRunner.java:266) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:263) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runners.Suite.runChild(Suite.java:128) at org.junit.runners.Suite.runChild(Suite.java:27) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
It seems to not like one of my test member fields being private, but is not telling me which one it has a problem with. All examples of unit tests I have seen, the only public must be the ExpectedException rule.

mwecs4sa

mwecs4sa1#

对不起,我是一个笨蛋。问题是@参数(x)内部成员需要是公共的,而不是私有的。
我花了很长时间在谷歌上搜索这个。:-)

0md85ypi

0md85ypi2#

在我的情况下,这个代码保证了我的生命安全

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

相关问题