Java 使用Spring、JUNIT、MockMvc和Hamcrest测试控制器

Java 使用Spring、JUNIT、MockMvc和Hamcrest测试控制器,java,spring,junit,hamcrest,mockmvc,Java,Spring,Junit,Hamcrest,Mockmvc,我正在尝试测试我的一个控制器,它在get方法上返回一个对象列表,以填充我页面上的下拉列表 我正在尝试使用MockMvc和Hamcrest编写一个JUnit测试来测试它 我想比较对象列表并测试它是否失败 我已经在Test.java中创建了一个静态对象列表,并且从model.attribute方法中获得了一个对象列表 测试:如果两个对象列表相等且不包含任何其他对象 我的对象称为Option,它有3个属性。键、值和选定项。我必须检查列表中是否存在所有密钥 我无法创建匹配器来执行相同的操作。我正在尝试创

我正在尝试测试我的一个控制器,它在get方法上返回一个对象列表,以填充我页面上的下拉列表

我正在尝试使用MockMvc和Hamcrest编写一个JUnit测试来测试它

我想比较对象列表并测试它是否失败

我已经在Test.java中创建了一个静态对象列表,并且从model.attribute方法中获得了一个对象列表

测试:如果两个对象列表相等且不包含任何其他对象

我的对象称为Option,它有3个属性。键、值和选定项。我必须检查列表中是否存在所有密钥

我无法创建匹配器来执行相同的操作。我正在尝试创建一个匹配器来比较我的列表

到目前为止,我已经做了以下工作:

@Before
public void setup() throws Exception {
    // This would build a MockMvc with only the following controller
    this.mockMvc = MockMvcBuilders.standaloneSetup(openAccountController)
            .build();
}

@Test
public void testOpenAccount() {
    try {
        setAllLegislations();
        this.mockMvc
                .perform(get("/open_account.htm"))
                // This method is used to print out the actual httprequest
                // and httpresponse on the console.
                .andDo(print())
                // Checking if status is 200
                .andExpect(status().isOk())
                .andExpect(
                        model().attributeExists("appFormAccountPlans",
                                "appFormLiraLegislations",
                                "appFormLrspLegislations",
                                "appFormRlspLegislations"))
                .andExpect(
                        model().attribute("appFormAccountPlans", hasSize(5)))
                .andExpect(
                        model().attribute("appFormLiraLegislations",
                                hasSize(8)))
                .andExpect(
                        model().attribute("appFormLrspLegislations",
                                hasSize(2)))
                .andExpect(
                        model().attribute("appFormRlspLegislations",
                                hasSize(1)))
                .andExpect(
                        model().attribute(
                                "appFormLiraLegislations",
                                hasKeyFeatureMatcher(getLiraLegislations(allLegislations))));


private Matcher<List<Option>> hasKeyFeatureMatcher(
        final List<Option> expectedOptions) {
    return new FeatureMatcher<List<Option>, List<Option>>(
            equalTo(expectedOptions), "Options are", "was") {

        @Override
        protected List<Option> featureValueOf(List<Option> actualOptions) {
            boolean flag = false;
            if (actualOptions.size() == expectedOptions.size()) {
                for (Option expectedOption : expectedOptions) {
                    for (Option actualOption : actualOptions) {
                        if (expectedOption.getKey().equals(
                                actualOption.getKey())) {
                            flag = true;
                        } else {
                            flag = false;
                            break;
                        }
                    }
                }
            }
            if (flag)
                return actualOptions;
            else
                return null;
        }
    };
}

private List<Option> getLiraLegislations(List<Option> legislation) {

    List<Option> liraLegislations = new ArrayList<Option>();
    Iterator<Option> iterator = legislation.iterator();
    while (iterator.hasNext()) {
        Option option = iterator.next();
        if (LIRA_LEGISLATIONS.contains(option.getKey())) {
            liraLegislations.add(option);
        }
    }
    return liraLegislations;
}

private List<Option> allLegislations;

public List<Option> getAllLegislations() {
    return allLegislations;
}

public void setAllLegislations() {
    allLegislations = new ArrayList<Option>();
    for (String key : ALL_LEGISLATIONS) {
        Option option = new Option();
        option.setKey(key);
        allLegislations.add(option);
    }
}

private static final Set<String> ALL_LEGISLATIONS = new HashSet<String>(
        Arrays.asList(AccountLegislationEnum.AB.toString(),
                AccountLegislationEnum.MB.toString(),
                AccountLegislationEnum.NB.toString(),
                AccountLegislationEnum.NL.toString(),
                AccountLegislationEnum.NS.toString(),
                AccountLegislationEnum.ON.toString(),
                AccountLegislationEnum.QC.toString(),
                AccountLegislationEnum.SK.toString(),
                AccountLegislationEnum.BC.toString(),
                AccountLegislationEnum.FE.toString(),
                AccountLegislationEnum.NT.toString(),
                AccountLegislationEnum.PE.toString(),
                AccountLegislationEnum.YT.toString(),
                AccountLegislationEnum.NU.toString(),
                AccountLegislationEnum.UNKNOWN.toString()));

提前感谢。

当您使用key属性正确实现Option对象hashCode和equals方法时,您的生活肯定会更轻松;然后你可以简单地写:

model().attribute("appFormLiraLegislations",getLiraLegislations(allLegislations)))
并依靠list1.equalslist2方法为您完成这项工作

选项hashCode和equals实现:

public class Option {

    private String key;
    private String label;

    ...

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((key == null) ? 0 : key.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Option other = (Option) obj;
        if (key == null) {
            if (other.key != null)
                return false;
        } else if (!key.equals(other.key))
            return false;
        return true;
    }

}

上面的方法是由我的IDE生成的。我也不知道Option类的确切结构是什么,所以我在key属性的基础上添加了label属性。

正确实现Option对象hashCode和使用key属性的equals方法后,您的生活肯定会更轻松;然后你可以简单地写:

model().attribute("appFormLiraLegislations",getLiraLegislations(allLegislations)))
并依靠list1.equalslist2方法为您完成这项工作

选项hashCode和equals实现:

public class Option {

    private String key;
    private String label;

    ...

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((key == null) ? 0 : key.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Option other = (Option) obj;
        if (key == null) {
            if (other.key != null)
                return false;
        } else if (!key.equals(other.key))
            return false;
        return true;
    }

}

上面的方法是由我的IDE生成的。我也不知道Option类的确切结构,所以我在key属性之外添加了label属性。

我创建了一个自定义Hamcrest匹配器,通过检查大小和键来比较选项列表

private Matcher<List<Option>> hasOptionsFeatureMatcher(
        final List<Option> expectedOptions) {
    return new FeatureMatcher<List<Option>, List<Option>>(
            equalTo(expectedOptions), "Options are", "Options were") {

        @Override
        protected List<Option> featureValueOf(List<Option> actualOptions) {
            boolean flag = false;
            if (expectedOptions.size() == actualOptions.size()) {
                for (Option expected : expectedOptions) {
                    for (Option actual : actualOptions) {
                        if (expected.getKey().equals(actual.getKey())) {
                            flag = true;
                            break;
                        } else {
                            flag = false;
                        }
                    }
                }
            } else
                flag = false;
            if (flag)
                return expectedOptions;
            else
                return null;
        }

    };
执行情况如下:

private static final ImmutableBiMap<String, String> LIRA = new ImmutableBiMap.Builder<String, String>()
        .put(AccountLegislationEnum.AB.toString(), "ALBERTA")
        .put(AccountLegislationEnum.MB.toString(), "MANITTOBA")
        .put(AccountLegislationEnum.NB.toString(), "NEW BRUNSWICK")
        .put(AccountLegislationEnum.NL.toString(), "NEWFOUNDLAND")
        .put(AccountLegislationEnum.NS.toString(), "NOVA SCOTIA")
        .put(AccountLegislationEnum.ON.toString(), "ONTARIO")
        .put(AccountLegislationEnum.QC.toString(), "QUEBEC")
        .put(AccountLegislationEnum.SK.toString(), "SASKATCHEWAN")
        .put(AccountLegislationEnum.UNKNOWN.toString(), "UNKNOWN").build();

private List<Option> prepareOptions(ImmutableBiMap<String, String> map) {
    List<Option> legislations = new ArrayList<Option>();
    for (Map.Entry<String, String> entry : map.entrySet()) {
        String key = entry.getKey();
        String value = entry.getValue();
        Option option = new Option();
        option.setKey(key);
        option.setValue(value);
        legislations.add(option);
    }
    return legislations;
}


.andExpect(model().attribute("appFormLiraLegislations",hasOptionsFeatureMatcher(prepareOptions(LIRA))))

我创建了一个自定义Hamcrest匹配器,通过检查大小和键来比较选项列表

private Matcher<List<Option>> hasOptionsFeatureMatcher(
        final List<Option> expectedOptions) {
    return new FeatureMatcher<List<Option>, List<Option>>(
            equalTo(expectedOptions), "Options are", "Options were") {

        @Override
        protected List<Option> featureValueOf(List<Option> actualOptions) {
            boolean flag = false;
            if (expectedOptions.size() == actualOptions.size()) {
                for (Option expected : expectedOptions) {
                    for (Option actual : actualOptions) {
                        if (expected.getKey().equals(actual.getKey())) {
                            flag = true;
                            break;
                        } else {
                            flag = false;
                        }
                    }
                }
            } else
                flag = false;
            if (flag)
                return expectedOptions;
            else
                return null;
        }

    };
执行情况如下:

private static final ImmutableBiMap<String, String> LIRA = new ImmutableBiMap.Builder<String, String>()
        .put(AccountLegislationEnum.AB.toString(), "ALBERTA")
        .put(AccountLegislationEnum.MB.toString(), "MANITTOBA")
        .put(AccountLegislationEnum.NB.toString(), "NEW BRUNSWICK")
        .put(AccountLegislationEnum.NL.toString(), "NEWFOUNDLAND")
        .put(AccountLegislationEnum.NS.toString(), "NOVA SCOTIA")
        .put(AccountLegislationEnum.ON.toString(), "ONTARIO")
        .put(AccountLegislationEnum.QC.toString(), "QUEBEC")
        .put(AccountLegislationEnum.SK.toString(), "SASKATCHEWAN")
        .put(AccountLegislationEnum.UNKNOWN.toString(), "UNKNOWN").build();

private List<Option> prepareOptions(ImmutableBiMap<String, String> map) {
    List<Option> legislations = new ArrayList<Option>();
    for (Map.Entry<String, String> entry : map.entrySet()) {
        String key = entry.getKey();
        String value = entry.getValue();
        Option option = new Option();
        option.setKey(key);
        option.setValue(value);
        legislations.add(option);
    }
    return legislations;
}


.andExpect(model().attribute("appFormLiraLegislations",hasOptionsFeatureMatcher(prepareOptions(LIRA))))

你能解释一下吗?很抱歉,我在这个问题上遇到了困难。谢谢@Pavla,我从来没有想过用这种方式来比较!他真是个魅力人物!有没有办法不使用上述方法来实现这一点?这将改变我的生产代码,我正试图避免!请给我建议一条路!你能解释一下吗?很抱歉,我在这个问题上遇到了困难。谢谢@Pavla,我从来没有想过用这种方式来比较!他真是个魅力人物!有没有办法不使用上述方法来实现这一点?这将改变我的生产代码,我正试图避免!请给我建议一条路!