35

我正在使用 EasyMock(2.4 版)和 TestNG 来编写 UnitTest。

我有以下情况,我无法更改定义类层次结构的方式。

我正在测试扩展 ClassA 的 ClassB。

B类看起来像这样

public class ClassB extends ClassA  {

  public ClassB()
    {
        super("title");
    }

    @Override
    public String getDisplayName() 
    {
        return ClientMessages.getMessages("ClassB.title");
    }

}

A类代码

public abstract class ClassA {
    private String title;

    public ClassA(String title)
    {
        this.title = ClientMessages.getMessages(title);
    }

    public String getDisplayName()
    {
        return this.title;
    }
}

ClientMessages 类代码

public class ClientMessages {
    private static MessageResourse messageResourse;

    public ClientMessages(MessageResourse messageResourse) 
    {
        this.messageResourse = messageResourse;
    }
    public static String getMessages(String code) 
    {
        return messageResourse.getMessage(code);

    }
}

MessageResource 类代码

public class MessageResourse {
    public String getMessage(String code) 
    {
        return code;
    }
}

测试B类

import static org.easymock.classextension.EasyMock.createMock;

import org.easymock.classextension.EasyMock;
import org.testng.Assert;
import org.testng.annotations.Test;

public class ClassBTest
{
    private MessageResourse mockMessageResourse = createMock(MessageResourse.class);
    private ClassB classToTest;
    private ClientMessages clientMessages;


    @Test
    public void testGetDisplayName()
    {

    EasyMock.expect(mockMessageResourse.getMessage("ClassB.title")).andReturn("someTitle");

        clientMessages = new ClientMessages(mockMessageResourse);

        classToTest = new ClassB();

        Assert.assertEquals("someTitle" , classToTest.getDisplayName());
        EasyMock.replay(mockMessageResourse);
    }
}

当我运行这个测试时,我得到以下异常:

java.lang.IllegalStateException:缺少前面方法调用 getMessage("title") 的行为定义

在调试我发现的是,它没有考虑模拟方法调用 mockMessageResourse.getMessage("ClassB.title")因为它是从构造函数(ClassB 对象创建)调用的。

任何人都可以帮我在这种情况下如何测试。

谢谢。

4

5 回答 5

48

您需要EasyMock.replay(mock)在调用被测方法之前调用。调用被测方法后,您可以调用EasyMock.verify(mock)以验证模拟是否被调用。

接下来,您需要expect使用“title”参数添加另一个调用,因为您调用了两次。

代码:

EasyMock.expect(mockMessageResourse.getMessage("title")).andReturn("title");    
EasyMock.expect(mockMessageResourse.getMessage("ClassB.title")).andReturn("someTitle");
EasyMock.replay(mockMessageResourse);
clientMessages = new ClientMessages(mockMessageResourse);

classToTest = new ClassB();

Assert.assertEquals("someTitle" , classToTest.getDisplayName());
EasyMock.verify(mockMessageResourse);
于 2010-06-09T11:00:34.957 回答
23

就我而言,这是由于省略了返回值规范(andReturn(...))引起的。 http://www.smcmaster.com/2011/04/easymock-issue-1-missing-behavior.html了解更多详情。

于 2013-04-29T08:58:41.357 回答
3

这可能有多种原因(someMock在此答案中是您的模拟对象的名称)。一方面,您可能需要期待通过

expect(someMock.someMethod(anyObject()).andReturn("some-object");

就像Reda 的回答一样。也可能是您replay(someMock)在使用模拟之前忘记打电话了,就像您在Julien Rentrop 的回答中看到的那样。

最后一件可能没有在这里提到的事情是,您之前在测试中在其他地方使用了模拟,而忘记通过reset(someMock).

如果您有多个这样的单元测试,则可能会发生这种情况:

private Object a = EasyMock.createMock(Object.class);

@Test
public void testA() throws Exception {
   expect(a.someThing()).andReturn("hello");
   replay(a);

   // some test code and assertions etc. here
   verify(a);
}

@Test
public void testB() throws Exception {
   expect(a.someThing()).andReturn("hello");
   replay(a);

   // some test code and assertions etc. here
   verify(a);
}

这将在一个带有 IllegalStateException 的测试中失败,因为模拟 a 在用于下一个测试之前没有被重置。要解决它,您可以执行以下操作:

private Object a = EasyMock.createMock(Object.class);

@Test
public void testA() throws Exception {
   expect(a.someThing()).andReturn("hello");
   replay(a);

   // some test code and assertions etc. here
   verify(a);
}

@Test
public void testB() throws Exception {
   expect(a.someThing()).andReturn("hello");
   replay(a);

   // some test code and assertions etc. here
   verify(a);
}

@After
public void tearDown() throws Exception {
   reset(a); // reset the mock after each test
}
于 2017-07-27T07:17:23.397 回答
1

您应该在通话replay之后expect和使用模拟之前拨打电话。在这种情况下,您应该将测试更改为以下内容:

@Test
public void testGetDisplayName()
{ 

    EasyMock.expect(mockMessageResourse.getMessage("ClassB.title")).andReturn("someTitle");
    EasyMock.replay(mockMessageResourse);

    clientMessages = new ClientMessages(mockMessageResourse);

    classToTest = new ClassB();

    Assert.assertEquals("someTitle" , classToTest.getDisplayName());
}
于 2018-05-14T09:44:29.933 回答
0

对我来说,发生这个异常是因为我试图存根的方法是final(我没有意识到的)。

如果你想存根一个final方法,你需要使用Powermock

于 2020-09-16T17:38:43.487 回答