官网地址https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2wiki地址https://github.com/mockito/m
Junit常用注解 作用@Test 测试方法@Ignore 忽略测试方法@BeforeClass 所有测试方法前执行一次 ,修饰的方法必须为static@AfterClass 所有测试方法后执行一次 ,修饰的方法必须为static@Before 初始化方法,每个方法前都执行一次@After 释放资源,每个方法后都执行一次@RunWith 指定一个特殊的运行器@SuteClasses 将需要进行测试的类列表作为参数传入1.Junit 4 的单元测试用例执行顺序为:@BeforeClass –> @Before –> @Test –> @After –> @AfterClass;2.每一个测试方法的调用顺序为:@Before –> @Test –> @After。3.@Test两个参数(1) expected用于测试会抛出的异常,注意expected不起到catch作用,抛出异常后的代码不会被执行;(2) timeout,传入指定的毫秒数,用于超时测试。
***********************************************************注解创建*****************************************一:/**引入mock的对象*/@MockBeanprivate EclpService eclpService;二:@Beforepublic void init(){//当调用eclpService中的某个方法时返回某些值when(mock.someMethod()).thenReturn(value)//验证eclpService中的某个方法是否被调用verify(mock).someMethod()}****************************************************************************************************---------------------------------------------------创建mock对象的方式----------------------------(1)普通方法普通方法中,被测试类可以写接口,因为可以手动new出实现类public class UserServiceTest {private UserService userService;private UserDao mockUserDao;@Beforepublic void setUp() {mockUserDao = mock(UserDao.class);userService = new UserServiceImpl();userService.setUserDao(mockUserDao);}(2)通过注解被@InjectMocks注解标注的属性,可以自动注入标记@Mock、@Spy等注解的属性值@InjectMocks标注的属性不能使用接口,因为@InjectMocks不能传入参数指明实现类public class UserServiceTest {@InjectMocksprivate UserServiceImpl userService;@Mockprivate UserDao mockUserDao;@Beforepublic void setUp() {MockitoAnnotations.initMocks(this);}(3)注解创建参考上文***注解创建****---------------------------------------------------mockito的使用-------------------------------when(mock.someMethod()).thenReturn(value1).thenReturn(value2);when(mock.someMethod()).thenReturn(value1, value2);when(mock.someMethod()).thenReturn(value1);when(mock.someMethod()).thenReturn(value2);另一种风格doReturn,主要用于spy对象的情况下doReturn(value1).doReturn(value2).when(mock).someMethod();对 void 方法进行方法预期设定doNothing().when(mock).someMethod();对方法设定返回异常when(mock.someMethod()).thenThrow(new RuntimeException());对 void 方法进行方法预期设定doThrow(new RuntimeException()).when(mock).someMethod();参数匹配器比如 any(User.class),匹配任意User对象;anyString()匹配任意字符串;anyInt()匹配任意int型Mock对象的行为验证(1)验证方法的调用次数通过 verify(mock,times(?)).someMethod()验证方法的调用次数,是常用的验证方式,包括可以验证指定明确的方法被调用次数、某方法未被调用。或一个方法总体被调用次数。Mockito除了提供times(N)方法供我们调用外,还提供了很多可选的方法:never() 没有被调用,相当于times(0)atLeast(N) 至少被调用N次atLeastOnce() 相当于atLeast(1)atMost(N) 最多被调用N次(2) 超时验证通过timeout,并制定毫秒数验证超时。注意,如果被调用多次,times还是需要的。(3) 方法调用顺序通过InOrder对象,验证方法的执行顺序,如上例子中,如果mock的get(0)和get(1)方法反过来则测试不通过。这里mock2其实没有被调用过。所以不需要些。(4) verifyNoMoreInteractions查询是否存在被调用,但未被验证的方法,如果存在则抛出异常。这里因为验证了get(anyInt()),相当于所有的get方法被验证,所以通过。(5) verifyZeroInteractions查询对象是否未产生交互,如果传入的mock对象的方法被调用过,则抛出异常。这里mock2的方法没有被调用过,所有通过。(6) 利用ArgumentCaptor(参数捕获器)捕获方法参数进行验证通过 ArgumentCaptor 对象的forClass(Class<T> clazz)方法来构建ArgumentCaptor对象。然后便可在验证时对方法的参数进行捕获,最后验证捕获的参数值。如果方法有多个参数都要捕获验证,那就需要创建多个ArgumentCaptor对象处理。当某个对象进行了多次调用后,比如mock对象。这时调用argument.getValue()获取到的是最后一次调用的参数。如果要获取所有的参数值可以调用argument.getAllValues(),它将返回参数值的List。Spy-对象的监视Mock 对象只能调用stubbed 方法,调用不了它真实的方法。但Mockito 可以监视一个真实的对象,这时对它进行方法调用时它将调用真实的方法,同时也可以stubbing 这个对象的方法让它返回我们的期望值。另外不论是否是真实的方法调用都可以进行verify验证。和创建mock对象一样,对于final类、匿名类和Java的基本类型是无法进行spy的。监视对象监视一个对象需要调用spy(T object)方法,如下面的代码中spy变量就在监视LinkedList实例。List spy = spy(new LinkedList());下面是一个官方给出的例子,仅供参考@Testpublic void spyTest() {List list = new LinkedList();List spy = spy(list);// optionally, you can stub out some methods:when(spy.size()).thenReturn(100);// using the spy calls real methodsspy.add("one");spy.add("two");// prints "one" - the first element of a listSystem.out.println(spy.get(0));// size() method was stubbed - 100 is printedSystem.out.println(spy.size());// optionally, you can verifyverify(spy).add("one");verify(spy).add("two");}Demo:@Testpublic void save() {User user = new User();user.setLoginName("admin");// 第一次调用findUserByLoginName返回user 第二次调用返回nullwhen(mockUserDao.findUserByLoginName(anyString())).thenReturn(user).thenReturn(null);try {// 测试如果重名会抛出异常userService.save(user);// 如果没有抛出异常测试不通过failBecauseExceptionWasNotThrown(RuntimeException.class);} catch (ServiceException se) {}verify(mockUserDao).findUserByLoginName("admin");// userService.save(user);user.setPassword("123456");String userId = userService.save(user);// 断言返回结果assertThat(userId).isNotEmpty().hasSize(32);verify(mockUserDao, times(2)).findUserByLoginName(anyString());verify(mockUserDao).save(any(User.class));}@Testpublic void save2() {User user = new User();user.setLoginName("admin");user.setPassword("123456");userService.save(user);// 通过ArgumentCaptor(参数捕获器) 对传入参数进行验证ArgumentCaptor<User> argument = ArgumentCaptor.forClass(User.class);verify(mockUserDao).save(argument.capture());assertThat("admin").isEqualTo(argument.getValue().getLoginName());// stub 调用save方法时抛出异常doThrow(new ServiceException("测试抛出异常")).when(mockUserDao).save(any(User.class));try {userService.save(user);failBecauseExceptionWasNotThrown(RuntimeException.class);} catch (ServiceException se) {}}--------------------------------------------------断言:Assertions-------------------------------用来判断某个语句的结果是否为真或判断是否与预期相符由于JUnit的Assert是公认的烂API,所以不推荐使用,目前推荐使用的是AssertJ。-------------------------------------------------对字符串断言-------------------------------------@Testpublic void testString() {String str = null;// 断言null或为空字符串assertThat(str).isNullOrEmpty();// 断言空字符串assertThat("").isEmpty();// 断言字符串相等 断言忽略大小写判断字符串相等assertThat("Frodo").isEqualTo("Frodo").isEqualToIgnoringCase("frodo");// 断言开始字符串 结束字符穿 字符串长度assertThat("Frodo").startsWith("Fro").endsWith("do").hasSize(5);// 断言包含字符串 不包含字符串assertThat("Frodo").contains("rod").doesNotContain("fro");// 断言字符串只出现过一次assertThat("Frodo").containsOnlyOnce("do");// 判断正则匹配assertThat("Frodo").matches("..o.o").doesNotMatch(".*d");}--------------------------------------------------对数字断言------------------------------------------@Testpublic void testNumber() {Integer num = null;// 断言空assertThat(num).isNull();// 断言相等assertThat(42).isEqualTo(42);// 断言大于 大于等于assertThat(42).isGreaterThan(38).isGreaterThanOrEqualTo(38);// 断言小于 小于等于assertThat(42).isLessThan(58).isLessThanOrEqualTo(58);// 断言0assertThat(0).isZero();// 断言正数 非负数assertThat(1).isPositive().isNotNegative();// 断言负数 非正数assertThat(-1).isNegative().isNotPositive();}-----------------------------------------对日期断言-----------------------------------------@Testpublic void testDate() {// 断言与指定日期相同 不相同 在指定日期之后 在指定日期之钱assertThat(Dates.parse("2014-02-01")).isEqualTo("2014-02-01").isNotEqualTo("2014-01-01").isAfter("2014-01-01").isBefore(parse("2014-03-01"));// 断言 2014 在指定年份之前 在指定年份之后assertThat(DateTime.now().toDate()).isBeforeYear(2020).isAfterYear(2013);// 断言时间再指定范围内 不在指定范围内assertThat(parse("2014-02-01")).isBetween("2014-01-01", "2014-03-01").isNotBetween(parse("2014-02-02"), parse("2014-02-28"));// 断言两时间相差100毫秒Date d1 = new Date();Date d2 = new Date(d1.getTime() + 100);assertThat(d1).isCloseTo(d2, 100);// sets dates differing more and more from date1Date date1 = Dates.parseDatetimeWithMs("2003-01-01T01:00:00.000");Date date2 = parseDatetimeWithMs("2003-01-01T01:00:00.555");Date date3 = parseDatetimeWithMs("2003-01-01T01:00:55.555");Date date4 = parseDatetimeWithMs("2003-01-01T01:55:55.555");Date date5 = parseDatetimeWithMs("2003-01-01T05:55:55.555");// 断言 日期忽略毫秒,与给定的日期相等assertThat(date1).isEqualToIgnoringMillis(date2);// 断言 日期与给定的日期具有相同的年月日时分秒assertThat(date1).isInSameSecondAs(date2);// 断言 日期忽略秒,与给定的日期时间相等assertThat(date1).isEqualToIgnoringSeconds(date3);// 断言 日期与给定的日期具有相同的年月日时分assertThat(date1).isInSameMinuteAs(date3);// 断言 日期忽略分,与给定的日期时间相等assertThat(date1).isEqualToIgnoringMinutes(date4);// 断言 日期与给定的日期具有相同的年月日时assertThat(date1).isInSameHourAs(date4);// 断言 日期忽略小时,与给定的日期时间相等assertThat(date1).isEqualToIgnoringHours(date5);// 断言 日期与给定的日期具有相同的年月日assertThat(date1).isInSameDayAs(date5);}-------------------------------------对List断言--------------------------------------------@Testpublic void testList() {// 断言 列表是空的assertThat(newArrayList()).isEmpty();// 断言 列表的开始 结束元素assertThat(newArrayList(1, 2, 3)).startsWith(1).endsWith(3);// 断言 列表包含元素 并且是排序的assertThat(newArrayList(1, 2, 3)).contains(1, atIndex(0)).contains(2, atIndex(1)).contains(3).isSorted();// 断言 被包含与给定列表assertThat(newArrayList(3, 1, 2)).isSubsetOf(newArrayList(1, 2, 3, 4));// 断言 存在唯一元素assertThat(Lists.newArrayList("a", "b", "c")).containsOnlyOnce("a");}---------------------------------------对Map断言---------------------------------------------@Testpublic void testMap() {Map<String, Object> foo = Maps.newHashMap();foo.put("A", 1);foo.put("B", 2);foo.put("C", 3);// 断言 map 不为空 sizeassertThat(foo).isNotEmpty().hasSize(3);// 断言 map 包含元素assertThat(foo).contains(entry("A", 1), entry("B", 2));// 断言 map 包含keyassertThat(foo).containsKeys("A", "B", "C");// 断言 map 包含valueassertThat(foo).containsValue(3);}---------------------------------------对Class断言------------------------------------@Testpublic void testClass() {// 断言 是注解assertThat(Magical.class).isAnnotation();// 断言 不是注解assertThat(Ring.class).isNotAnnotation();// 断言 存在注解assertThat(Ring.class).hasAnnotation(Magical.class);// 断言 不是借口assertThat(Ring.class).isNotInterface();// 断言 是否为指定Class实例assertThat("string").isInstanceOf(String.class);// 断言 类是给定类的父类assertThat(Person.class).isAssignableFrom(Employee.class);}@Magicalpublic enum Ring {oneRing, vilya, nenya, narya, dwarfRing, manRing;}@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface Magical {}public class Person {}public class Employee extends Person {}-------------------------------------使用fail方法-------------------------------------------@Testpublic void testFail() {try {fail("在不检查任何条件的情况下使断言失败。显示一则消息");} catch (AssertionError ae) {logger.info("可以通过catch捕获该Error");}try {failBecauseExceptionWasNotThrown(ServiceException.class);} catch (AssertionError ae) {logger.info("可以通过catch捕获该Error");}}
文章转载自open资料酷,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




