这是关于如何使用模拟对象对Java类进行单元测试的一般问题.
我可以用这个例子总结我的问题.
假设我有一个名为MyInterface.java的接口和一个不覆盖equals()的"TwoString"对象
"TwoString.java"
private String string1;
private String string2;
public TwoString(String string1, String string2) {
this.string1 = string1;
this.string2 = string2;
}
...getters..setters..
Run Code Online (Sandbox Code Playgroud)
"MyInterface.java"
void callMe(TwoString twoString);
Run Code Online (Sandbox Code Playgroud)
然后我有"MyClass.java"对象.它的构造函数接受MyInterface的具体实现.
MyClass methodToTest()包含以某种方式创建TwoString对象的逻辑.假设它将被创建为
new TwoString("a","b")
Run Code Online (Sandbox Code Playgroud)
因此,当调用methodToTest()时,它会创建这个将传递给接口方法callMe(TwoString twoString)的TwoString对象.
我基本上想要模拟界面.使用此mock创建一个MyClass对象.然后验证是否使用TwoString的特定实例调用了mock方法.
我正在使用EasyMock,这是一些java代码
"MyClassTest.java"
public void test() throws Exception {
MyInterface myInterfaceMock = createMock(MyInterface.class);
MyClass myClass = new MyClass(myInterfaceMock);
myInterfaceMock.callMe(new TwoString("a","b")); <--- fails here
expectLastCall();
replay(myInterfaceMock);
myClass.methodToTest();
verify(myInterfaceMock);
Run Code Online (Sandbox Code Playgroud)
这就是问题所在.我期待在调用中的TwoString对象
myInterfaceMock.callMe(new TwoString("a","b"));
Run Code Online (Sandbox Code Playgroud)
与MyClass.methodToTest()中生成的不同,因为TwoString.java不会覆盖equals.
我可以跳过TwoString实例上的问题
myInterfaceMock.callMe((TwoString)anyObject());
Run Code Online (Sandbox Code Playgroud)
但我想确保使用TwoString的特定实例调用接口方法,该实例包含"a"作为string1而"b"作为string2.
在这种情况下,TwoString对象非常简单,并且很容易覆盖equals方法 - 但是如果我需要检查更复杂的对象该怎么办.
谢谢
我将尝试使用此示例使其更具可读性
public …
Run Code Online (Sandbox Code Playgroud) 我目前正在尝试学习如何使用easymock.我有以下代码:
List list = EasyMock.createMock(List.class);
EasyMock.expect(list.size()).andReturn(0);
EasyMock.replay(list);
EasyMock.verify(list);
Run Code Online (Sandbox Code Playgroud)
至少对我来说这应该工作 - 列表初始化时没有任何内容,大小应该返回0.但是我得到以下错误:
java.lang.AssertionError:
Expectation failure on verify:
size(): expected: 1, actual: 0
Run Code Online (Sandbox Code Playgroud)
我觉得这很奇怪,所以我将线路中的0改为1并重新进行测试.我得到了同样的错误.有谁知道我做错了什么?提前致谢!
假设我有以下方法:
public void runLoop(SomeIterator it){
while(it.hasNext()){
//do something
}
}
Run Code Online (Sandbox Code Playgroud)
现在我想传入一个SomeIterator
Mock对象,该对象将返回Boolean.TRUE
以进入循环,但我也希望它Boolean.FALSE
在某个时刻返回(例如10次之后),是否有办法使PowerMock /发生这种情况EasyMock的?
在此先感谢您的帮助.
我想模拟静态方法以及类的非静态方法.我的来源看起来像:
Run Code Online (Sandbox Code Playgroud)
public class XDSUtilityManager
{
private static XDSUtilityManager xdsUtilMgr = new XDSUtilityManager();
private XDSUtilityManager()
{
xdsUtilMgrImpl = new XDSUtilityManagerImpl();
}
public static XDSUtilityManager getInstance()
{
return (xdsUtilMgr == null ) ? new XDSUtilityManager() : xdsUtilMgr;
}
public XMLDocument getXMLDocument(final String absoluteKey, final XDSClient xdsClient)
{
return getXMLDocument(absoluteKey, xdsClient, false);
}
}
I want to mock static method getInstance(). I want getInstance() to return mock object of XDSUtilityManager class. Also I want to mock getXMLDocument() which is not static.
And …
我将代码中方法的返回值更改void
为和Object
.然后两次junit测试失败,说明expect(...).andReturn(...)
缺失了.添加后,一个测试是固定的,另一个仍然抛出一个看起来有点奇怪的异常:
java.lang.IllegalStateException:matcher调用在期望之外使用
适用于一个但不适用于另一个的代码是:
expect(myMock.foo(1l,FooEnum.A)).andReturn(EasyMock.anyObject(String.class));
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
我想添加方法测试,其中包含 CompletableFuture:
public void report(List<String> srcList) {
if (srcList != null) {
...
CompletableFuture.runAsync(() ->
....
srcList.forEach(src-> downloader.send(url)));
}
}
Run Code Online (Sandbox Code Playgroud)
我想测试一下,那个方法send
被调用了。我的测试看起来像:
@Test
public void _test() {
List<String> events = new ArrayList();
events.add("http://xxxx//");
events.add("http://xxxx//");
expect(downloader.send(events.get(0))).andReturn("xxx").times(2);
replay(downloader);
eventReporter.report(events);
verify(downloader);
}
Run Code Online (Sandbox Code Playgroud)
我得到这样的错误Downloader.send("http://xxxx//"): expected: 2, actual: 0
避免此错误的一种方法是设置Thread.sleep(100);
超时。然后线程将等待并验证该方法是否已调用。但这会增加测试时间。
还有其他方法可以使用 EasyMock 测试多线程吗?
当尝试测试时,当需要从下面的控制器中删除一个方法时,事情会变得很棘手
@RequestMapping(value="/remove", method=RequestMethod.POST)
public String remove(
@ModelAttribute("id") String id, Model model
) {
bookService.removeOne(Long.parseLong(id.substring(8)));
List<Book> bookList = bookService.findAll();
model.addAttribute("bookList", bookList);
return "redirect:/book/bookList";
}
Run Code Online (Sandbox Code Playgroud)
我的测试从下面的之前测试方法中的模拟注入开始
@Before
public void setUp() {
bookService = createMock(BookService.class);
ReflectionTestUtils.setField(bookController, "bookService", bookService);
userRepository= createMock(UserRepository.class);
ReflectionTestUtils.setField(bookController, "userRepository", userRepository);
mockMvc = standaloneSetup(bookController)
.setMessageConverters(new MappingJackson2HttpMessageConverter())
.build();
}
Run Code Online (Sandbox Code Playgroud)
最后是测试,尝试删除一本书,而不是让它写入。我该如何继续?
@Test
public void bookRemoveTest() throws Exception {
securityService.autologin("admin", "admin");
Book book = new Book();
book.setId(1L);
expect(bookService.removeOne(anyObject( class));).andReturn(book);
replay(bookService);
MvcResult result = mockMvc
.perform(post("/book/remove")
.accept(MediaType.TEXT_HTML)
.contentType(MediaType.TEXT_HTML))
.andExpect(status().isOk())
.andReturn();
String controllerResult = result.getResponse().getContentAsString();
} …
Run Code Online (Sandbox Code Playgroud) 使用EasyMock设置void方法的期望时,是否可以将Object数组指定为方法的参数之一?
例如,如果我们有这样的事情:
Errors mockErrors = createMock(Errors.class);
...
mockErrors.rejectValue(Object[]{"5", "2"});
mockErrors.replay();
classUnderTest.someMethod();
Run Code Online (Sandbox Code Playgroud)
在ClassUnderTest中,someMethod调用rejectValue(Object [] {"5","2"});
然而,尽管期望被设置为正在调用的内容,但是easy mock会抱怨意外的方法调用.
> Unexpected method call rejectValue(["5", "2"]):
> rejectValue(["5", "2"]): expected: 1, actual: 0
Run Code Online (Sandbox Code Playgroud)
我认为这是因为在引擎盖下它依赖于Object []上的equals方法,并且由于两者不同,它返回false并且不满足条件.
有办法解决吗?因为我没有使用expect()设置期望我可以使用any()...有没有办法在void方法上做同样的事情?
我从easymock和JUnit测试用例中得到了一些莫名其妙的行为.我收到了IllegalStateException: missing behavior definition for the preceeding method call: myCollaborator.getCurrentApplyDate() Usage is: expect(a.foo()).andXXX()
.我正在使用easymock 3.1来模拟myCollaborator
正在测试的JUnit 4测试类classUnderTest
.
classUnderTest
需要打两次电话myCollaborator
.只需一个电话,一切正常.@Before
我的JUnit测试类中的setup方法:
@Before
public void setUp() throws Exception {
mockCollaborator = EasyMock.createMock(MyCollaborator.class);
classUnderTest = new myObject(mockCollaborator);
data = new MyDTO();
// other setup code for data omitted
EasyMock.expect(mockCollaborator.getCurrentApplyDate()).andReturn(new java.sql.Date(123456789));
// comment out this expectation for now so it works
// EasyMock.expect(mockCollaborator.getCurrentBatch()).andReturn("123");
EasyMock.replay();
}
Run Code Online (Sandbox Code Playgroud)
在classUnderTest.process()
说我与两个调用测试方法myCollaborator
,第二个注释掉,使其工作:
public MyDTO process(MyDTO data) throws Exception { …
Run Code Online (Sandbox Code Playgroud) 我目前在使用EasyMock进行单元测试时遇到问题。
Expectation failure on verify:
FileConverter.convert(file, file2): expected: 1, actual: 1
Run Code Online (Sandbox Code Playgroud)
这是该类中唯一的失败,并且在下面的verify方法上失败。我已经尝试过搜索该消息,但是这只会显示“ expected:1,actual:1 (+1) ”的结果,而+1表示错误有所不同。
我试图简化失败的EasyMock测试的结构以进行演示。请原谅任何错别字:
@Test
public void testScan() {
String[] testFiles = { "file", "file2" };
FileConverter converterMock = EasyMock.createMock(FileConverter.class);
Poller poller = new Poller(new File("testFolder"), converterMock);
for (String testFile : testFiles) {
converterMock.convert(new File(testFile));
EasyMock.expectLastCall().once();
}
EasyMock.replay(converterMock);
for (String testFile : testFiles) {
poller.scan();
}
EasyMock.verify(converterMock);
}
Run Code Online (Sandbox Code Playgroud)
我认为代码本身并不特别相关,但是出于完整性考虑,我将其包括在内-我真正想要的是解释EasyMock.verify方法的上下文中“预期1,实际1”的含义。
提前致谢!
我正在进行Junit测试,我需要将Easymock和Class对象一起工作来测试.
以下是我的代码段
@Before
public void setUp() {
request=EasyMock.createMock(SlingHttpServletRequest.class);
response=EasyMock.createMock(SlingHttpServletResponse.class);
}
@Test
public void testImage() {
RequestContext ctx = new RequestContext();
// RequestContext and RequestContext Util are both classes defined in Project
expect(RequestContextUtil.setupContext(request,response)).andReturn(ctx);
// This line is throwing an error , so I am not able to add replay or verify method
}
Run Code Online (Sandbox Code Playgroud)
我试着看一个例子,我可以一起使用Easy mock和Class对象,我找不到适合我的情况.任何人都能指出我的一个例子吗?
我正在使用PowerMock和EasyMock来模拟系统类Math.class
。但是出现错误:
java.lang.NoClassDefFoundError:org / easymock / MockType
班级代码 -
class ToBeTested {
public int getAbsoulte(int a) {
int res = Math.abs(a);
return res;
}
}
Run Code Online (Sandbox Code Playgroud)
测试类代码-
import static org.easymock.EasyMock.expect;
import static org.mockito.ArgumentMatchers.anyInt;
import java.lang.invoke.MethodHandles;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.powermock.api.easymock.PowerMock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@PrepareForTest({ ToBeTested.class, Math.class })
@PowerMockIgnore({ "com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "org.w3c.*", "com.sun.org.apache.xalan.*",
"javax.activation.*", "javax.management.*" })
@RunWith(PowerMockRunner.class)
public class ToTestPowerMockito {
@InjectMocks
private ToBeTested toBeTested;
@Test
public void testAbsolute() { …
Run Code Online (Sandbox Code Playgroud)