Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/309.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 模拟的简单单元测试不断失败;模拟对象未传递给类?_Java_Unit Testing_Oop_Mockito_Powermock - Fatal编程技术网

Java 模拟的简单单元测试不断失败;模拟对象未传递给类?

Java 模拟的简单单元测试不断失败;模拟对象未传递给类?,java,unit-testing,oop,mockito,powermock,Java,Unit Testing,Oop,Mockito,Powermock,我有一个简单的单元测试失败了。希望我能用简单的术语解释这一点,因为我已经看了几个小时了,我看到了问题所在,但我对mock背后的基本理论不太熟悉,所以我有点困惑,无法解决它。我将很快总结这个问题,然后将代码粘贴到下面 基本上,在我名为getAllValidModelTest()的测试方法中,它使用for循环迭代对象类型DeviceModel的枚举值。只有5个:[EX3400_24P,EX4300_32F,EX4300_48MP,SRX_345,人造] 因此,在for循环中,在Assert语句(Ju

我有一个简单的单元测试失败了。希望我能用简单的术语解释这一点,因为我已经看了几个小时了,我看到了问题所在,但我对mock背后的基本理论不太熟悉,所以我有点困惑,无法解决它。我将很快总结这个问题,然后将代码粘贴到下面

基本上,在我名为getAllValidModelTest()的测试方法中,它使用for循环迭代对象类型DeviceModel的枚举值。只有5个:[EX3400_24P,EX4300_32F,EX4300_48MP,SRX_345,人造]

因此,在for循环中,在Assert语句(Junit)之前,它对getDevice(deviceId)进行静态方法调用,并从那里返回一个Device对象。GetAllValidModelTest()中for循环下的第一行模拟elementMock对象,以返回当前的model,该模型在DeviceModels[]数组中迭代,该数组是从enums DeviceModel类的.values()调用返回的

因此,我的问题是,当它在我的for循环的第二次迭代中跳转(从1开始计数)时,断言失败,因为DeviceModel[]数组中的第0个元素显然是EX4300_32F,但在@Before setUp注释中,它被模拟为返回EX3400_24P。但奇怪的是,在getAllValidModelTest()方法中的for循环下,它再次被覆盖/模拟,以返回到当前模型,该模型在对elementMock对象调用.getModel时正在迭代,因此它应该返回相同的

这就是类SwitchDeviceFactoryTest.java的构造方式(带有单元测试的类):

这是我在测试前运行的设置方法。唯一重要的变量是elementMock对象,特别是被模拟以返回EX3400_24P对象的变量:

@Before
public void setup() throws Exception {
    secrets.setSecretsData(secretsData);
    PowerMockito.mockStatic(DataGatewayFactory.class);
    Mockito.when(DataGatewayFactory.getInstance()).thenReturn(dbMock);
    Mockito.when(dbMock.getTransportDeviceSecretsCrud()).thenReturn(transportDeviceSecretsCrud);
    Mockito.when(transportDeviceSecretsCrud.getServerSecretsInfo(anyString())).thenReturn(Optional.of(secrets));
    Mockito.when(transportDeviceSecretsCrud.getReportedSecretsInfo(anyString())).thenReturn(Optional.of(secrets));

    when(dbMock.getElementCrud()).thenReturn(elementCrud);
    doReturn(Optional.of(elementMock)).when(elementCrud).getById(anyString());
    Mockito.when(elementMock.getModel()).thenReturn(DeviceModel.EX3400_24P.getModel());

    Mockito.when(elementMock.getType()).thenReturn(ElementType.SWITCH);
    Mockito.when(dbMock.getSwitchConfigCrud()).thenReturn(switchConfigCrud);
    Mockito.when(switchConfigCrud.get(anyString())).thenReturn(Optional.of(swConfigMock));
    Mockito.when(swConfigMock.getIp()).thenReturn(ip);
    Mockito.when(dbMock.getRouterConfigCrud()).thenReturn(routerConfigCrud);
    Mockito.when(routerConfigCrud.get(anyString())).thenReturn(Optional.of(routerConfigMock));
    Mockito.when(routerConfigMock.getIp()).thenReturn(ip);
以及试验方法:

@Test
public void getAllValidModelsTest() throws Exception {
    for (DeviceModel model: DeviceModel.values()) {
        when(elementMock.getModel()).thenReturn(model.getModel());
        if (model == DeviceModel.SRX_345)
            when(elementMock.getType()).thenReturn(ElementType.ROUTER);
        else
            when(elementMock.getType()).thenReturn(ElementType.SWITCH);
        Device device = DeviceFactory.getDevice(deviceId);
        assertEquals(model, device.getModel());
    }
}
没有意义的是,我在重构代码,只更改了两行代码(elementCrud和elementMock.doReturn和.when调用),它在开发分支上运行得非常好

当我调试时,我可以看到在for循环的第二次迭代中,.getModel在静态getDevice方法中返回EX3400_24P对象,此时它应该返回model.getModel(),这将是在DeviceModels的.values()枚举数组中迭代的第二个对象。。。所以它应该是EX4300_32F

在“开发”分支上,此操作非常有效。。。。这就好像Mockito mock对象在myGetAllValidModelTest()方法(即Device Device=DeviceFactory.getDevice(deviceId);)中调用它之后,在getDevice方法内跳入DeviceFactory类时忘记了它应该做什么一样

以下是DeviceFactory类中的.getDevice方法:

public static Device getDevice(String serialNumber) throws Exception {
    IElement element = dataGateway.getElementCrud().getById(serialNumber).get();
    DeviceModel model = DeviceModel.valueOfLabel(element.getModel()); // right here is where it returns the wrong model... it returns EX3400_24P on the 2nd iteration
    log.info("Found device {} in database", serialNumber);

    if (serialNumber.startsWith(FakeDevicePrefix.ATGTEST.toString()) || serialNumber.startsWith(FakeDevicePrefix.FAKE.toString())) {
        log.info("Detected FAKE/ATG serial number. Using FAUX device.");
        model = DeviceModel.FAUX;
    }

    switch (element.getType()) {
        case SWITCH:
            SwitchConfig config = dataGateway.getSwitchConfigCrud().get(serialNumber).get();
            return getDevice(serialNumber, config.getIp(), model);
        case ROUTER:
            RouterConfig rconfig = dataGateway.getRouterConfigCrud().get(serialNumber).get();
            return getDevice(serialNumber, rconfig.getIp(), DeviceModel.SRX_345);
        case PTP:
        default:
            log.warn("Unsupported device type {}", element.getType().toString());
            throw new Exception("Unsupported device type " + element.getType().toString());
    }
}
我确实注释掉了/删除了一段代码,该代码在setUp()方法中使用@Before注释返回EX3400_24P,但是测试失败,此时出现了NULL指针异常

在跳入DeviceFactory.java类之前,.getModel方法如何知道返回我在上一个类(SwitchDeviceFactoryTest.java)中模拟它返回的内容?如果我没有将它作为变量传递到getDevice()方法中,它怎么会记得呢

因为这是一个静态方法,我需要使用PowerMock还是其他什么?这有什么改变吗


请帮忙

您的代码示例似乎加载了与问题不直接相关的内容。如果您提供一段最简单的代码来说明问题,其他人会更容易帮助您。@Dirk Herrmann感谢您的建议。我实际上解决了这个问题,并将在下面更新我所做的
public static Device getDevice(String serialNumber) throws Exception {
    IElement element = dataGateway.getElementCrud().getById(serialNumber).get();
    DeviceModel model = DeviceModel.valueOfLabel(element.getModel()); // right here is where it returns the wrong model... it returns EX3400_24P on the 2nd iteration
    log.info("Found device {} in database", serialNumber);

    if (serialNumber.startsWith(FakeDevicePrefix.ATGTEST.toString()) || serialNumber.startsWith(FakeDevicePrefix.FAKE.toString())) {
        log.info("Detected FAKE/ATG serial number. Using FAUX device.");
        model = DeviceModel.FAUX;
    }

    switch (element.getType()) {
        case SWITCH:
            SwitchConfig config = dataGateway.getSwitchConfigCrud().get(serialNumber).get();
            return getDevice(serialNumber, config.getIp(), model);
        case ROUTER:
            RouterConfig rconfig = dataGateway.getRouterConfigCrud().get(serialNumber).get();
            return getDevice(serialNumber, rconfig.getIp(), DeviceModel.SRX_345);
        case PTP:
        default:
            log.warn("Unsupported device type {}", element.getType().toString());
            throw new Exception("Unsupported device type " + element.getType().toString());
    }
}