【问题标题】:Can i set/change the return value of a mock after the mock is defined?定义模拟后,我可以设置/更改模拟的返回值吗?
【发布时间】:2015-04-08 10:43:04
【问题描述】:

我想在我的 setUp 方法中创建一个模拟,但在每个测试方法中定义具体的返回值。这有可能吗?

例如:

private List<Long> list; 

@Before
public void setUp() {
    when(mock.xxx()).thenReturn(list);
}

@Test
public void testEmptyList() {
    list = new ArrayList<Long>();

    // method call
}

@Test
public void testWithOneElement() {
    list = Arrays.asList(Long.valueOf(125L));

    // method call
}

编辑: 我能有的最好的情况是:

private List<Long> list = new ArrayList<Long>();

@Before
public void setUp() {
    when(mock.xxx()).thenReturn(list);
}

@Test
public void testEmptyList() {
    // method call
}

@Test
public void testWithOneElement() {
    list.add(Long.valueOf(123L));
    // method call
}

由于 Java 通过引用传递值,只要我们不为列表分配新列表,我们就可以添加值,并且 mock 将使用更新的列表。 但是,即使更改了 ObjectId,这种行为是否也可能发生?所以我模拟了一个方法调用,但定义了稍后返回什么?

例如:

private List<Long> list; 

@Before
public void setUp() {
    when(mock.xxx()).thenReturn(list);
}

@Test
public void testEmptyArrayList() {
    list = new ArrayList<Long>();
    // method call
}

@Test
public void testEmptyLinkedList() {
    list = new LinkedList<Long>();
    // method call
}

【问题讨论】:

  • 您可以将when(mock.xxx()).thenReturn(list); 分别添加到您的两个测试用例中,而不是在 setUp() 中。然后在 testEmpty 中返回一个空列表并在 testWithOneElement 中返回一个元素的列表
  • 显然我知道...我明确提出了这个问题,所以我不必单独模拟,因为我有很多测试方法,而不仅仅是2...

标签: java junit mocking mockito junit4


【解决方案1】:

你可以添加when(mock.xxx()).thenReturn(list);分别对您的测试用例而不是在 setUp() 中。然后在 testEmpty 中返回一个空列表并在 testWithOneElement 中返回一个元素的列表

private List<Long> list; 

@Before
public void setUp() {
    // Other setup here
}

@Test
public void testEmptyList() {
    list = new ArrayList<Long>();
    when(mock.xxx()).thenReturn(list); // return list with no element

    // method call
}

@Test
public void testWithOneElement() {
    list = Arrays.asList(Long.valueOf(125L));
    when(mock.xxx()).thenReturn(list);  // return list with one elemet

    // method call
}

【讨论】:

  • 显然我知道...我明确提出了这个问题,所以我不必单独模拟,因为我有很多测试方法,而不仅仅是2...
  • 顺便说一句,您必须在模拟定义之前设置属性列表!在您的情况下,您有一个空指针异常。
  • 您应该提到您已经意识到并正在寻找除此之外的其他选择。是的,已经在代码中注释了返回空列表和一个元素。
  • 感谢您的建议。但我已经写过“我想在我的 setUp 方法中创建一个模拟”......而不是“我想在任何地方模拟”
  • 你必须在你的模拟定义之前分配列表!在您的情况下,您有一个空指针异常..“list = new ArrayList....”,然后是“when(mock.xxx())....”
【解决方案2】:

所以..经过反复试验,我做了这样的事情:

private List<Long> list; 

@Before
public void setUp() {
    when(mock.xxx()).thenAnswer(
            new Answer<List<Long>>() {
                @Override
                public List<Long> answer(final InvocationOnMock invocation) {
                    return list;
                }
            });
}

@Test
public void testEmptyArrayList() {
    list = new ArrayList<Long>();
    // method call
}

@Test
public void testEmptyLinkedList() {
    list = new LinkedList<Long>();
    // method call
}

由于我们现在在 setUp 中定义,不是“返回值”,而是“准备返回值的被调用方法”,并且由于该方法将在首先运行时,我们没有得到一个nullPointer,我们在每个方法中分配的值都会被返回。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-13
    • 2016-01-07
    相关资源
    最近更新 更多