【问题标题】:Junit Mockito for global java.util.Map用于全局 java.util.Map 的 Junit Mockito
【发布时间】:2020-10-06 06:31:44
【问题描述】:

我正在尝试测试一个方法,但它有一个为空的全局变量,请指导我,以便我可以为全局变量赋值,即 Map

我的朱尼特:

public class ErrorTest {

    @Mock
    private DataSource db;

    @Mock
    private JdbcTemplate jdbcTemplate;

    @InjectMocks
    private RateServiceImpl rateService = new RateServiceImpl();

    @Mock
    private RaterDao raterDao;

    @Resource
    private MessageSource msg ;

    @Mock
    Map<String, StringAttribute> errorMap = new HashMap<String, StringAttribute>();

    @Before
    public void setup() throws IOException, InterruptedException {
        MockitoAnnotations.initMocks(this);
        MockMvcBuilders.standaloneSetup(rateService).build();
    }

    @Test
    public void findAllErrors() throws Exception {
        String error;

        List<Error> erList = new ArrayList<>();
        Error er27 = new ErrorImpl("27",
                "No detail found",
                "Please enter detail.");
        erList.add(er27);

        Error er22 = new ErrorImpl("1",
                "Maximum number  exceeded",
                "Please contact  Technical Support.");
        erList.add(er22);

        for (int index = 0; index < erList.size(); index++) {
            StringAttribute st = new StringAttributeImpl();
            st.setName(erList.get(index).getDescription());
            st.setValue(erList.get(index).getResolution());
            errorMap.put(erList.get(index).getCode(), st);
        }

        List<Error> errorList = raterDao.findAllErrors();
        assertThat(errorList, is(notNullValue()));

        StringAttribute map27 = errorMap.get("27");
        Mockito.when(rateService.findRwxlClientError("27")).thenReturn(map27);

        StringAttribute map22 = errorMap.get("22");
        Mockito.when(rateService.findRwxlClientError("22")).thenReturn(map22);

        assertTrue("ParseShipment failed", map27.getName().equals("No detail found"));

        assertTrue("ParseShipment failed", map22.getName().equals("Please contact  Technical Support."));

    }

}

我的主要课程:

@Service
public class RateServiceImpl implements RateService {

    protected final Log logger = LogFactory.getLog(getClass());

    @Autowired
    private RaterDao raterDao;

    private Map<String, StringAttribute> errorMap = new HashMap<String, StringAttribute>();

    @Resource
    private MessageSource msg;

    @PostConstruct
    public void init() throws Exception {
        **errorMap** = findAllClientErrors();
    }

public Map<String, StringAttribute> findAllClientErrors() throws Exception {

        List<Error> errorList = raterDao.findAllClientErrors();

        for (int index = 0; index < errorList.size(); index++) {
            StringAttribute st = new StringAttributeImpl();
            st.setName(errorList.get(index).getDescription());
            st.setValue(errorList.get(index).getResolution());
            errorMap.put(errorList.get(index).getCode(), st);
        }

        return errorMap;
    }


    @Override
    public StringAttribute findClientError(String code) throws Exception {

        StringAttribute error = new StringAttributeImpl();

        if (code.equals(Constants.ERROR_CODE_SETTING_UNAVAILABLE)) {
            error.setName(msg.getMessage("SETTING.MESSAGE.ERROR", null,null));
            error.setValue(msg.getMessage("SETTING.MESSAGE.RESOLUTION", null,null));
            return error;
        }

        StringAttribute map = errorMap.get(code);

        if (map == null || map.getName().isEmpty()) {
            error.setName(msg.getMessage("DEFAULT.MESSAGE", new Object[] { code }, null));
            error.setValue("");
        } else {
            error.setName(errorMap.get(code).getName());
            error.setValue(errorMap.get(code).getValue());
        }

        return error;
    }

    }

我尝试了多种解决方案但都不起作用,有时地图会变空或为空。 任何通过我的测试用例的解决方案都有效。 我想测试 findClientError(String code) 问题出在 errorMap

【问题讨论】:

  • 你的RateServiceImpl类很奇怪。你有一个errorMap 成员变量,它被初始化为一个空映射。然后,在finalAllClientErrors 中,您修改地图并将其返回。当它返回时,您将覆盖errorMap 成员变量。当findAllClientErrors 返回时,您可以通过不覆盖errorMap 来解决此问题。 (由于副作用,这仍然不是特别好的代码。更好的解决方案可能是在函数中创建并返回新地图并将结果附加到errorMap)

标签: junit hashmap mockito global-variables powermockito


【解决方案1】:

所以,你可以使用ReflectionUtils.setField 方法。我做了一个小例子,它和你的代码不完全一样,但总的来说你会明白的。

这是我正在测试的课程。做的几乎和你的例子一模一样。我有 hello 方法只是为了测试并检查它是否工作。

class RateService {
    private static Map<String, Object> errorMap = new HashMap<>();

    @PostConstruct
    public void init () {
        this.errorMap = findAllErrors();
    }

    private Map<String, Object> findAllErrors() {
        Map<String, Object> errorMap = new HashMap<>();
        errorMap.put("a", new Object());
        errorMap.put("b", new Object());
        errorMap.put("c", new Object());
        return errorMap;
    }

    // a method for demo purposes
    public String hello() {
        if (errorMap.size() > 0) {
            return String.join(",", errorMap.keySet());
        } else {
            return "Empty";
        }
    }
}

这是我的测试课。 setField 方法的第三个参数是要在该字段中设置的对象。因此,您可以在那里创建一个模拟对象或真实对象。我分配了一个带有虚拟值的真实对象。然后对此进行测试。

class MainTest {

    private RateService rateService;

    @BeforeEach
    void setUp() {
        this.rateService = new RateService();
    }

    private Map<String, Object> exampleErrorObjects() {
        Map<String, Object> errorMap = new HashMap<>();
        errorMap.put("x", new Object());
        errorMap.put("y", new Object());
        errorMap.put("z", new Object());
        return errorMap;
    }

    @Test
    void testHello() {
        // given:
        ReflectionTestUtils.setField(RateService.class, "errorMap", exampleErrorObjects());
        // when:
        final String result = this.rateService.hello();
        // then:
        assertEquals("x,y,z", result);
    }
}

我在测试方法中设置静态字段,因为您可能希望您的类在每个测试中处于不同的状态(基于errorMap 字段)。

【讨论】:

  • 这个抛出异常非法ArgumentException:在 org.springframework.test.util.ReflectionTestUtils 的目标 [class com.smc.rater.rating.RateServiceImpl] 上找不到类型为 [null] 的字段 [errorMap]。设置字段(ReflectionTestUtils.java:111)。我还创建了在 ReflectionTestUtils 中将 errorMap 作为第三个参数返回的真实对象
  • 这是因为,在我的示例中,“errorMap”是一个静态字段,而它是您的成员变量。我可能是错误地这样说的。将行更改为ReflectionTestUtils.setField(this.rateService, "errorMap", exampleErrorObjects()); 应该可以修复它。
  • 谢谢,我会试试的,这也像测试我自己的硬代码值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-19
  • 1970-01-01
  • 2019-12-23
  • 1970-01-01
相关资源
最近更新 更多