Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.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_Collections_Tdd - Fatal编程技术网

Java 如何测试列表是否<;?扩展对象>;他是一个非编撰者吗?

Java 如何测试列表是否<;?扩展对象>;他是一个非编撰者吗?,java,unit-testing,collections,tdd,Java,Unit Testing,Collections,Tdd,我正在寻找一种方法来测试某个给定的列表是否是不可修改的 我有一个对象,它有一个列表,以便提供诸如addNoMatter(NoMatter nm)之类的方法,而不是允许API客户端简单地执行.getNoMatters().add(nm)我总是返回此列表的不可修改版本,因此客户端仍然可以拥有该列表。我的做法如下: public List<NoMatter> getNoMatters() { return Collections.unmodifiableList(this.noMa

我正在寻找一种方法来测试某个给定的列表是否是不可修改的

我有一个对象,它有一个
列表
,以便提供诸如
addNoMatter(NoMatter nm)
之类的方法,而不是允许API客户端简单地执行
.getNoMatters().add(nm)我总是返回此列表的不可修改版本,因此客户端仍然可以拥有该列表。我的做法如下:

public List<NoMatter> getNoMatters() {
    return Collections.unmodifiableList(this.noMatters);
}
碰巧我似乎无法导入类型
UnmodifiableList
也无法导入
java.util.Collections$UnmodifiableRandomAccessList
,这就是我尝试
System.out.println(myObj.getNoMatters().getClass().getName())时得到的结果在控制台上

那么我怎样才能做到呢

注:我知道我可以通过以下测试:

@Test(expected = UnsupportedOperationException.class)
public void checkIfListIsImmutable(){
     this.myObj.getNoMatters().add(null);
}
编辑:上面的测试并不能保证我处理的列表不是不变的,因为我需要对可能修改我原始列表的每个方法进行测试,包括.remove()、.clear()、.shuffle()等!这就是为什么我不认为这是一个好的方式进行


>>>但我仍然相信,它甚至不接近一个优雅的解决方案 我真的认为这是你最好的选择。另一种(不那么优雅的)方法是检查类的名称

this.myObj.getNoMatters().getClass().getSimpleName().equals("UnmodifiableCollection")
问题是包装的不可修改集合是包私有的


我不认为期待出现异常有什么错,但那只是我。

我认为您的解决方案不仅合理,而且优雅。您希望测试您不能修改列表,并且您的测试简洁地证明了这一点。测试类的名称测试名称,而不是行为。在这种情况下,谁在乎名字


同样,如果我想测试我不能将null传递给某个方法,我会在测试中传递null,并期望出现IllegalArgumentException。

有点像黑客,但请尝试:

import java.util.*;
public class Main {
    public static void main(String[] args) {
        List<Integer> list=new LinkedList<Integer>();
        list.add(1);
        List<Integer> unmodifiableList=Collections.unmodifiableList(list);
        System.out.println(unmodifiableList.getClass());
        if(unmodifiableList.getClass().getName().contains("UnmodifiableList"))
            System.out.println(true);
    }
}
import java.util.*;
公共班机{
公共静态void main(字符串[]args){
列表=新建LinkedList();
增加第(1)款;
列表不可修改列表=集合。不可修改列表(列表);
System.out.println(unmodifiableList.getClass());
if(unmodifiableList.getClass().getName()包含(“unmodifiableList”))
System.out.println(真);
}
}
您可以使用来检查

Collections.unmodifiableList(someList).getClass().isInstance(listToCheck);
/e1
下面返回
false

Collections.unmodifiableList(new ArrayList<Object>()).getClass().isInstance(new ArrayList<Object>())
/e2
您的问题可能是因为
Collections#unmodifiableList
在某些时间返回
unmodifiableList
,在其余时间返回
UnmodifiableRandomAccessList
(代码见下文)。然而,由于
UnmodifiableRandomAccessList
扩展了
UnmodifiableList
,如果您得到一个
UnmodifiableList
的实例进行检查,您将获得金牌

要获取
UnmodifiableList
的实例,可以使用
Collections.UnmodifiableList(newlinkedlist())
LinkedList
未实现
RandomAccess
,因此不会返回
UnmodifiableRandomAccessList
的实例

集合的代码#不可修改列表

public static <T> List<T> unmodifiableList(List<? extends T> list) {
        return (list instanceof RandomAccess ?
                new UnmodifiableRandomAccessList<>(list) :
                new UnmodifiableList<>(list));
}
static class UnmodifiableRandomAccessList<E> extends UnmodifiableList<E> implements RandomAccess

为什么要测试列表是不可变的?您的“替代”解决方案是一条路:您应该专注于测试类的行为,而不是它的状态

我的意思是,您并不真正关心您的方法是否返回
UnmodifiableList
的实例或其他任何东西。谁在乎呢?你的测试当然不应该。如果以后更改实现以实现完全相同的行为,您的测试不应失败

那么你想测试什么呢?用户无法向列表中添加任何内容?然后编写一个测试(如您所建议的),向列表中添加一些内容,并期望出现异常。他们不能从列表中删除任何内容?对另一个测试进行同样的操作。等等


测试像这样的负面案例确实很优雅,我发现在类的函数覆盖中经常会忘记它。适当的覆盖范围应明确说明您的类不允许的内容,并说明在这些情况下的预期内容。

我希望类似于
集合的内容。检查(T元素)
在不实际修改集合的情况下完成工作

除了投票最多的答案外,还有
Collections.EmptyList
(至少)这是另一个不可修改的列表

因此,如果我真的必须创建一个实用程序作为一个肮脏的解决方案,我将添加我的“易于识别”元素,看看它是否抛出UnsupportedOperationException,那么这意味着它是不可修改的。否则,我必须立即删除输入的内容。

除了回答之外,还说明确实应该对行为进行测试,并包括作者的评论,他建议添加一个空列表,以便在列表不是不可修改的情况下不会被修改,我在这里添加了一个示例,说明如何检查列表的不可修改性

代码尝试添加一个空列表,如果可能的话,抛出一个IllegalArgumentException,否则为了方便起见,返回原始列表,现在可以确保它是不可修改的

/**
 * Ensures that a list is unmodifiable (i.e. that nothing can be added).
 *
 * Unmodifiable lists can e.g. be created by Collections.UnmodifiableList().
 *
 * @param list a list
 * @param <T> element type of the list
 * @return the list that is verified to be unmodifiable
 */
public static <T> List<T> verifyUnmodifiable(List<T> list) {
    try {
        list.addAll(Collections.emptyList());
    } catch (Exception e) {
        return list;
    }
    throw new IllegalArgumentException("List is modifiable.");
}
/**
*确保列表不可修改(即不能添加任何内容)。
*
*例如,不可修改列表可以由集合创建。不可修改列表()。
*
*@param列出一个列表
*@param列表的元素类型
*@返回经验证不可修改的列表
*/
公共静态列表验证不可修改(列表列表){
试一试{
list.addAll(Collections.emptyList());
}捕获(例外e){
退货清单;
}
抛出新的IllegalArgumentException(“列表可修改”);
}

不确定是否测试移除、清除。。。这也是必要的。不能添加通常是不可修改的一个很好的指示。

如果API很难测试,这通常是一种API需要改进的气味。在里面
static class UnmodifiableRandomAccessList<E> extends UnmodifiableList<E> implements RandomAccess
/**
 * Ensures that a list is unmodifiable (i.e. that nothing can be added).
 *
 * Unmodifiable lists can e.g. be created by Collections.UnmodifiableList().
 *
 * @param list a list
 * @param <T> element type of the list
 * @return the list that is verified to be unmodifiable
 */
public static <T> List<T> verifyUnmodifiable(List<T> list) {
    try {
        list.addAll(Collections.emptyList());
    } catch (Exception e) {
        return list;
    }
    throw new IllegalArgumentException("List is modifiable.");
}