是否可以在同一个类上进行单元测试方法调用(按顺序调用它们的次数和次数)?
即。模板方法如下:
abstract class FooBarBaz {
public abstract void foo();
public abstract void bar();
public abstract void baz();
// I want to create a unit test for this method, in the following order
public myTemplateMethod() {
foo(); // i want to check foo first;
bar(); // i want to check bar second;
baz(); // i want to check baz third;
}
}
编辑 - 发布Mockito代码实施
import junit.framework.TestCase;
import org.mockito.Mockito;
public class FooBarBazTest extends TestCase {
public void testMyTemplateMethodWithMockito() {
FooBarBaz mocked = Mockito.mock(FooBarBaz.class);
mocked.myTemplateMethod();
Mockito.verify(mocked, Mockito.times(1)).foo();
Mockito.verify(mocked, Mockito.times(1)).bar();
Mockito.verify(mocked, Mockito.times(1)).baz();
}
}
编辑 - 添加了堆栈跟踪
testMyTemplateMethodWithMockito(sample.FooBarBazTest) Time elapsed: 0.326 sec <<< FAILURE!
Wanted but not invoked:
fooBarBaz.foo();
-> at sample.FooBarBazTest.testMyTemplateMethodWithMockito(FooBarBazTest.java:14)
However, there were other interactions with this mock:
-> at sample.FooBarBazTest.testMyTemplateMethodWithMockito(FooBarBazTest.java:12)
at sample.FooBarBazTest.testMyTemplateMethodWithMockito(FooBarBazTest.java:14)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at junit.framework.TestCase.runTest(TestCase.java:168)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:232)
at junit.framework.TestSuite.run(TestSuite.java:227)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:59)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:115)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:102)
at org.apache.maven.surefire.Surefire.run(Surefire.java:180)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:350)
at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1021)
答案 0 :(得分:4)
看看Mockito它内置了这种行为。
从他们的文件:
6.按顺序验证
List firstMock = mock(List.class);
List secondMock = mock(List.class);
//using mocks
firstMock.add("was called first");
secondMock.add("was called second");
//create inOrder object passing any mocks that need to be verified in order
InOrder inOrder = inOrder(firstMock, secondMock);
//following will make sure that firstMock was called before secondMock
inOrder.verify(firstMock).add("was called first");
inOrder.verify(secondMock).add("was called second");
和:
4.验证确切的调用次数/至少x /从不
//using mock
mockedList.add("once");
mockedList.add("twice");
mockedList.add("twice");
mockedList.add("three times");
mockedList.add("three times");
mockedList.add("three times");
//following two verifications work exactly the same - times(1) is used by default
verify(mockedList).add("once");
verify(mockedList, times(1)).add("once");
//exact number of invocations verification
verify(mockedList, times(2)).add("twice");
verify(mockedList, times(3)).add("three times");
//verification using never(). never() is an alias to times(0)
verify(mockedList, never()).add("never happened");
//verification using atLeast()/atMost()
verify(mockedList, atLeastOnce()).add("three times");
verify(mockedList, atLeast(2)).add("five times");
verify(mockedList, atMost(5)).add("three times");
答案 1 :(得分:2)
使用模拟框架很好,但如果您不想依赖外部依赖,只需创建一个实现抽象类的测试类。让foo,bar,baz方法的抽象实现将字符串'foo','bar','baz'添加到共享列表中,然后在测试方法中断言它们以正确的顺序存在于列表中。
编辑 - 我用mockito和非模拟方式编写了测试。他们都通过了 - 我之前没有使用过mockito,我可能想尝试一下......
import junit.framework.TestCase;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class FooBarBazTests extends TestCase {
@Test
public void testMyTemplateMethod() {
List tracker = new ArrayList();
SimpleFooBarBaz toTest = new SimpleFooBarBaz(tracker);
toTest.myTemplateMethod();
assertEquals("foo", tracker.get(0));
// more assertions
}
@Test
public void testMyTemplateMethodWithMockito() {
FooBarBaz mocked = mock(FooBarBaz.class);
mocked.myTemplateMethod();
// times(1) is unnecessary, but explicit
verify(mocked, times(1)).foo();
verify(mocked, times(1)).bar();
verify(mocked, times(1)).baz();
}
class SimpleFooBarBaz extends FooBarBaz {
List tracker;
SimpleFooBarBaz(List tracker) {
this.tracker = tracker;
}
public void foo() {
tracker.add("foo");
}
@Override
public void bar() {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void baz() {
//To change body of implemented methods use File | Settings | File Templates.
}
// others there
}
}