Java测试套件

您所在的位置:网站首页 junit和mockito Java测试套件

Java测试套件

2024-07-16 20:21:19| 来源: 网络整理| 查看: 265

说明

        在第一份工作中,我经历了我的第一个商用的项目,是一个微服务模块(后台管理模块),我所在的团队做的是南方电网的项目。不扯远了,当时我开始做的时候在想要以什么方式开发时,我的组长因担心项目到期出不了成品,所以催促我快点产出代码。之后就有了这篇文章,由于我为了赶进度而没有做单元测试,这导致了项目的后半部分bug产出数量随着代码的增加而增加,更郁闷地是修改之后为了配合前端都得去服务器部署一次,浪费的时间不比写单元测试少,也让我明白了单元测试的重要性。我的要求是让自己学会TDD测试驱动开发的开发习惯,且写下该文记录自己学习的历程。

        该文将介绍单元测试框架Junit,模仿对象的框架Mockito。文章介绍核心的概念,感兴趣可以进入参考文章或者书籍进一步阅读。

参考文章以及书籍

《测试驱动开发》 Hamcrest 总结 深入JUnit源码之Rule JUnit4.11 理论机制 @Theory 完整解读 Junit4.8之Category Mockito官方文档中文版 Junit测试Controller-RESTful接口 IDEA代码覆盖率测试

测试驱动开发-TDD

        也有人把这种流程称为极限编程。

        测试驱动开发是使用测试框架的目的,能更好更快地让我们写完代码然后傲游二次元或者是出门做个现充。

碧海之蓝 -- 羞耻的生活喜剧番

        测试驱动开发指的是就是字面上的意思,用测试来驱动整个开发流程,也就是在写开发代码前先提前写测试代码,然后写业务代码来让测试通过。这里只是简单地概念性介绍,主要是要避免“开发后简单地验证结果”而转为“主动编写测试用例然后编写代码使用例通过”。

整个流程以就是不断重复下面几步:

|--->快速创建一个测试        |--->运行所有测试,发现新测试无法通过               |--->做一些细微的调整                      |--->运行所有测试,所有测试通过                            |--->重构代码,消除重复,优化代码结构

Junit

JUnit is a simple framework to write repeatable tests. It is an instance of the xUnit architecture for unit testing frameworks.

Junit是一个简单的测试框架,其官网涵盖大量的用例可以作为使用参考。/home/harry

Junit 4 官网的用例 Assertions-断言机制

        断言机制是判断结果是否正确的机制,总是以“assertXXXX”格式出现,只要有一条验证结果与预想不匹配,则测试不通过。         Hamcrest提供了其他的一些断言方式,请查看Hamcrest 总结。

import static org.hamcrest.CoreMatchers.allOf; import static org.hamcrest.CoreMatchers.anyOf; import static org.hamcrest.CoreMatchers.both; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.everyItem; import static org.hamcrest.CoreMatchers.hasItems; import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.sameInstance; import static org.hamcrest.CoreMatchers.startsWith; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import java.util.Arrays; import org.hamcrest.core.CombinableMatcher; import org.junit.Test; public class AssertTests { @Test public void testAssertArrayEquals() { byte[] expected = "trial".getBytes(); byte[] actual = "trial".getBytes(); assertArrayEquals("failure - byte arrays not same", expected, actual); } @Test public void testAssertEquals() { assertEquals("failure - strings are not equal", "text", "text"); } @Test public void testAssertFalse() { assertFalse("failure - should be false", false); } @Test public void testAssertNotNull() { assertNotNull("should not be null", new Object()); } @Test public void testAssertNotSame() { assertNotSame("should not be same Object", new Object(), new Object()); } @Test public void testAssertNull() { assertNull("should be null", null); } @Test public void testAssertSame() { Integer aNumber = Integer.valueOf(768); assertSame("should be same", aNumber, aNumber); } // JUnit Matchers assertThat @Test public void testAssertThatBothContainsString() { assertThat("albumen", both(containsString("a")).and(containsString("b"))); } @Test public void testAssertThatHasItems() { assertThat(Arrays.asList("one", "two", "three"), hasItems("one", "three")); } @Test public void testAssertThatEveryItemContainsString() { assertThat(Arrays.asList(new String[] { "fun", "ban", "net" }), everyItem(containsString("n"))); } // Core Hamcrest Matchers with assertThat @Test public void testAssertThatHamcrestCoreMatchers() { assertThat("good", allOf(equalTo("good"), startsWith("good"))); assertThat("good", not(allOf(equalTo("bad"), equalTo("good")))); assertThat("good", anyOf(equalTo("bad"), equalTo("good"))); assertThat(7, not(CombinableMatcher. either(equalTo(3)).or(equalTo(4)))); assertThat(new Object(), not(sameInstance(new Object()))); } @Test public void testAssertTrue() { assertTrue("failure - should be true", true); } } Runner-测试执行器

        你写的测试代码都会在这些测试执行器中运行,Junit默认的执行器为BlockJUnit4ClassRunner,当你不指定时,就会使用这个类来运行测试。可以使用注解@RunWith(xxxx)来指定运行测试的执行器。

Suite组合测试

        Suite测试在Junit中是测试一组测试用例,用途比较明确,就是有些操作是需要执行多个操作才能完成的,所以可以组成一个组来进行测试。

import org.junit.runner.RunWith; import org.junit.runners.Suite; @RunWith(Suite.class) @Suite.SuiteClasses({ TestFeatureLogin.class, TestFeatureLogout.class, TestFeatureNavigate.class, TestFeatureUpdate.class }) public class FeatureTestSuite { // the class remains empty, // used only as a holder for the above annotations } 指定期待异常

        如果没有抛出指定异常则测试不通过。

@Test(expected = IndexOutOfBoundsException.class) public void empty() { new ArrayList().get(0); } 忽略测试

        可以让测试暂时失效。

@Ignore("Test is ignored as a demonstration") @Test public void testSame() { assertThat(1, is(1)); } 测试失效时间 @Test(timeout=1000) public void testWithTimeout() { ... } Rule机制

JUnit中的Rule是对@BeforeClass、@AfterClass、@Before、@After等注解的另一种实现,其中@ClassRule实现的功能和@BeforeClass、@AfterClass类似;@Rule实现的功能和@Before、@after类似。JUnit引入@ClassRule和@Rule注解的关键是想让以前在@BeforeClass、@AfterClass、@Before、@After中的逻辑能更加方便的实现重用,因为@BeforeClass、@AfterClass、@Before、@After是将逻辑封装在一个测试类的方法中的,如果实现重用,需要自己将这些逻辑提取到一个单独的类中,再在这些方法中调用,而@ClassRule、@Rule则是将逻辑封装在一个类中,当需要使用时,直接赋值即可,对不需要重用的逻辑则可用匿名类实现,也因此,JUnit在接下来的版本中更倾向于多用@ClassRule和@Rule。

        Junit @Rule和@ClassRule只能注解在字段上,且该字段必须实现TestRule接口,Junit提供了一些默认实现类。

深入JUnit源码之Rule类图 - 来源于博文《深入JUnit源码之Rule》 public class DigitalAssetManagerTest { @Rule public final TemporaryFolder tempFolder = new TemporaryFolder(); @Rule public final ExpectedException exception = ExpectedException.none(); @Test public void countsAssets() throws IOException { File icon = tempFolder.newFile("icon.png"); File assets = tempFolder.newFolder("assets"); createAssets(assets, 3); DigitalAssetManager dam = new DigitalAssetManager(icon, assets); assertEquals(3, dam.getAssetCount()); } private void createAssets(File assets, int numberOfAssets) throws IOException { for (int index = 0; index < numberOfAssets; index++) { File asset = new File(assets, String.format("asset-%d.mpg", index)); Assert.assertTrue("Asset couldn't be created.", asset.createNewFile()); } } @Test public void throwsIllegalArgumentExceptionIfIconIsNull() { exception.expect(IllegalArgumentException.class); exception.expectMessage("Icon is null, not a file, or doesn't exist."); new DigitalAssetManager(null, null); } } Theory机制

        Theory是一个自动化填充参数并进行多次参数测试的一个机制,可以自己实现注解来定义参数。下面的代码中,定义了两个实参,而当测试 filenameIncludesUsername 方法时,形参username会被两个实参填充并各执行一次。

@RunWith(Theories.class) public class UserTest { @DataPoint public static String GOOD_USERNAME = "optimus"; @DataPoint public static String USERNAME_WITH_SLASH = "optimus/prime"; @Theory public void filenameIncludesUsername(String username) { assumeThat(username, not(containsString("/"))); assertThat(new User(username).configFileName(), containsString(username)); } } Test Fixture 测试固件

The test fixture is everything we need to have in place to exercise the SUT

Test Fixture(测试固件)是指一个测试运行所需的固定环境。

Fixtures 是测试中非常重要的一部分。他们的主要目的是建立一个固定/已知的环境状态以确保 测试可重复并且按照预期方式运行。Junit提供了一些方法来设置fixture,可以用来设置测试方法所需的环境数据等,允许你精确的定义你的Fixtures。大致上分为三类: Test Fixtures 规则(Rules&RulesClass) Theories

大致包含了如下过程

@BeforeClass setUpClass @Before setUp @Test test2() @After tearDown @Before setUp @Test test1() @After tearDown @AfterClass tearDownClass Category机制

一种级联的测试方式, @IncludeCategory(XXX.class)可以包含@Category(XXX.class) @ExcludeCategory(XXX.class)将会忽略@Category(XXX.class) 细节参照博文

Mock和Mockito

        mock其实是一种工具的简称,他最大的功能是帮你把单元测试的耦合分解开,如果你的代码对另一个类或者接口有依赖,它能够帮你模拟这些依赖,并帮你验证所调用的依赖的行为。

对象间存在依赖关系 使用Mock来模仿对象,消除耦合关系

下面的代码来自官网示例

1. 验证某些行为 // 静态导入会使代码更简洁 import static org.mockito.Mockito.*; // mock creation 创建mock对象 List mockedList = mock(List.class); //using mock object 使用mock对象 mockedList.add("one"); mockedList.clear(); //verification 验证 verify(mockedList).add("one"); verify(mockedList).clear(); 2. 制作测试桩 //You can mock concrete classes, not only interfaces // 你可以mock具体的类型,不仅只是接口 LinkedList mockedList = mock(LinkedList.class); //stubbing // 测试桩 when(mockedList.get(0)).thenReturn("first"); when(mockedList.get(1)).thenThrow(new RuntimeException()); //following prints "first" // 输出“first” System.out.println(mockedList.get(0)); //following throws runtime exception // 抛出异常 System.out.println(mockedList.get(1)); //following prints "null" because get(999) was not stubbed // 因为get(999) 没有打桩,因此输出null System.out.println(mockedList.get(999)); //Although it is possible to verify a stubbed invocation, usually it's just redundant //If your code cares what get(0) returns then something else breaks (often before even verify() gets executed). //If your code doesn't care what get(0) returns then it should not be stubbed. Not convinced? See here. // 验证get(0)被调用的次数 verify(mockedList).get(0);

        默认情况下,所有的函数都有返回值。mock函数默认返回的是null,一个空的集合或者一个被对象类型包装的内置类型,例如0、false对应的对象类型为Integer、Boolean。

3. 参数匹配器(ArgumentMatchers) //stubbing using built-in anyInt() argument matcher // 使用内置的anyInt()参数匹配器 when(mockedList.get(anyInt())).thenReturn("element"); //stubbing using custom matcher (let's say isValid() returns your own matcher implementation): // 使用自定义的参数匹配器( 在isValid()函数中返回你自己的匹配器实现 ) when(mockedList.contains(argThat(isValid()))).thenReturn("element"); //following prints "element" // 输出element System.out.println(mockedList.get(999)); //you can also verify using an argument matcher // 你也可以验证参数匹配器 verify(mockedList).get(anyInt()); verify(mock).someMethod(anyInt(), anyString(), eq("third argument")); //above is correct - eq() is also an argument matcher // 上述代码是正确的,因为eq()也是一个参数匹配器 // 该示例展示了如何多次应用于测试桩函数的验证

        参数匹配器使验证和测试桩变得更灵活,参考API文档。

4. 验证函数的确切、最少、从未调用次数 //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默认验证的就是times(1) 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) // 使用never()进行验证,never相当于times(0) verify(mockedList, never()).add("never happened"); //verification using atLeast()/atMost() // 使用atLeast()/atMost() verify(mockedList, atLeastOnce()).add("three times"); verify(mockedList, atLeast(2)).add("five times"); verify(mockedList, atMost(5)).add("three times"); 5. 使用stub抛出异常 doThrow(new RuntimeException()).when(mockedList).clear(); //following throws RuntimeException: // 调用这句代码会抛出异常 mockedList.clear(); 6. 验证执行顺序 // A. Single mock whose methods must be invoked in a particular order // A. 验证mock一个对象的函数执行顺序 List singleMock = mock(List.class); //using a single mock singleMock.add("was added first"); singleMock.add("was added second"); //create an inOrder verifier for a single mock // 为该mock对象创建一个inOrder对象 InOrder inOrder = inOrder(singleMock); //following will make sure that add is first called with "was added first, then with "was added second" // 确保add函数首先执行的是add("was added first"),然后才是add("was added second") inOrder.verify(singleMock).add("was added first"); inOrder.verify(singleMock).add("was added second"); // B. Multiple mocks that must be used in a particular order // B .验证多个mock对象的函数执行顺序 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 // 为这两个Mock对象创建inOrder对象 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"); // Oh, and A + B can be mixed together at will 7. 确保交互(interaction)操作不会执行在mock对象上 //using mocks - only mockOne is interacted // 使用Mock对象 mockOne.add("one"); //ordinary verification // 普通验证 verify(mockOne).add("one"); //verify that method was never called on a mock // 验证某个交互是否从未被执行 verify(mockOne, never()).add("two"); //verify that other mocks were not interacted // 验证mock对象没有交互过 verifyZeroInteractions(mockTwo, mockThree); 8. 简化mock对象的创建 public class ArticleManagerTest { @Mock private ArticleCalculator calculator; @Mock private ArticleDatabase database; @Mock private UserProvider userProvider; private ArticleManager manager; // 需要执行下面语句来初始化注解的使用 @Before public void initMocks() { MockitoAnnotations.initMocks(this); } //也可以在测试类加上注解@RunWith(MockitoJUnit44Runner.class) //或者使用MockitoJUnitRunner 9. 为连续的调用做测试桩 when(mock.someMethod("some arg")) .thenThrow(new RuntimeException()) .thenReturn("foo"); //First call: throws runtime exception: // 第一次调用 : 抛出运行时异常 mock.someMethod("some arg"); //Second call: prints "foo" // 第二次调用 : 输出"foo" System.out.println(mock.someMethod("some arg")); //Any consecutive call: prints "foo" as well (last stubbing wins). // 后续调用 : 也是输出"foo" System.out.println(mock.someMethod("some arg")); // 简短的写法,第一次调用时返回"one",第二次返回"two",第三次返回"three" when(mock.someMethod("some arg")) .thenReturn("one", "two", "three"); 10. 为回调做测试桩

Allows stubbing with generic Answer interface. 运行为泛型接口Answer打桩。

when(mock.someMethod(anyString())).thenAnswer(new Answer() { Object answer(InvocationOnMock invocation) { Object[] args = invocation.getArguments(); Object mock = invocation.getMock(); return "called with arguments: " + args; } }); //Following prints "called with arguments: foo" // 输出 : "called with arguments: foo" System.out.println(mock.someMethod("foo")); 11. 监控真实对象

        你可以为真实对象创建一个监控(spy)对象。当你使用这个spy对象时真实的对象也会也调用,除非它的函数被stub了。

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* methods // 通过spy对象调用真实对象的函数 spy.add("one"); spy.add("two"); //prints "one" - the first element of a list // 输出第一个元素 System.out.println(spy.get(0)); //size() method was stubbed - 100 is printed // 因为size()函数被打桩了,因此这里返回的是100 System.out.println(spy.size()); //optionally, you can verify // 交互验证 verify(spy).add("one"); verify(spy).add("two"); 12. 为下一步的断言捕获参数(ArgumentCaptor) ArgumentCaptor argument = ArgumentCaptor.forClass(Person.class); // 参数捕获 verify(mock).doSomething(argument.capture()); // 使用equal断言 assertEquals("John", argument.getValue().getName()); 13. TDD与BDD(行为驱动开发)结合使用 import static org.mockito.BDDMockito.*; Seller seller = mock(Seller.class); Shop shop = new Shop(seller); public void shouldBuyBread() throws Exception { //given given(seller.askForBread()).willReturn(new Bread()); //when Goods goods = shop.buyBread(); //then assertThat(goods, containBread()); } 14. @Captor,@Spy,@ InjectMocks

@Captor 简化 ArgumentCaptor 的创建 - 当需要捕获的参数是一个令人讨厌的通用类,而且你想避免编译时警告。

@Spy - 你可以用它代替 spy(Object) 方法

@InjectMocks - 自动将模拟对象或侦查域注入到被测试对象中。需要注意的是 @InjectMocks 也能与 @Spy 一起使用,这就意味着 Mockito 会注入模拟对象到测试的部分测试中。它的复杂度也是你应该使用部分测试原因。

15. 验证超时 //passes when someMethod() is called within given time span verify(mock, timeout(100)).someMethod(); //above is an alias to: verify(mock, timeout(100).times(1)).someMethod(); //passes when someMethod() is called *exactly* 2 times within given time span verify(mock, timeout(100).times(2)).someMethod(); //passes when someMethod() is called *at least* 2 times within given time span verify(mock, timeout(100).atLeast(2)).someMethod(); //verifies someMethod() within given time span using given verification mode //useful only if you have your own custom verification modes. verify(mock, new Timeout(100, yourOwnVerificationMode)).someMethod();

以上内容,足以让我们使用Junit 4进行日常代码的单元测试

使用Junit + Mockito 对Service做单元测试 public interface RegisterUserService { boolean insert(String passid,String msisdn,String email) throws SQLException; } @Service("registerUserService") public class RegisterUserServiceImpl implements RegisterUserService { private Logger loggor = Logger.getLogger(getClass()); @Autowired private UserMapper userMapper; @Autowired private PassidUserMapper passidUserMapper; @Autowired @Qualifier("redisService") private CacheService redisService; @Override @Transactional public boolean insert(String passid, String msisdn, String email) throws SQLException { if (StringUtils.isEmpty(passid)) return false; User user = new User(); if (!StringUtils.isEmpty(msisdn)) user.setPhoneNo(msisdn); if (!StringUtils.isEmpty(email)) user.setEmail(email); PassidUser passidUser = new PassidUser(); String serverCode = ServerCodeConfig.serverCodeMap .get(PayUtil.ipAddress); if (StringUtils.isEmpty(serverCode)) { serverCode = "999"; } String userid = serverCode + UIDUtil.next(); passidUser.setUserid(userid); passidUser.setPassid(passid); user.setPassid(passid); user.setUserid(userid); Date date = new Date(); user.setCreateTime(date); user.setUpdateTime(date); user.setDeleteFlag(0); /*if(loggor.isInfoEnabled()){ loggor.info("passid:" + passid + " userid:" + userid + " msisdn:" + msisdn + " email:" + email); }*/ int result = passidUserMapper.insert(passidUser); if (passidUserMapper.insert(passidUser) > 0 && userMapper.insertSelective(user) > 0) redisService.set("passid:" + passid + ":userid", userid); else throw new SQLException("数据插入失败,数据回滚"); return true; } } @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration("file:src/main/resources/conf/springConfig.xml") public class RegisterUserServiceImplTest { @InjectMocks private RegisterUserService registerUserService = new RegisterUserServiceImpl(); @Mock private UserMapper userMapper; @Mock private PassidUserMapper passidUserMapper; @Mock private CacheService redisService; @Before public void setUp() { MockitoAnnotations.initMocks(this); when(passidUserMapper.insert(any(PassidUser.class))).thenReturn(1); when(userMapper.insertSelective(any(User.class))).thenReturn(1); } @Test public void testInsert() throws Exception { String passid = "12344"; String msisdn = "18867131210"; String email = "[email protected]"; Assert.assertTrue(registerUserService.insert(passid, msisdn, email)); } } 使用SpringMVC,Junit, Mockito测试Controller(Restful接口) org.springframework spring-context ${spring.version} org.springframework spring-webmvc ${spring.version} junit junit ${junit.version} test org.hamcrest hamcrest-core ${hamcrest.core.version}/version> test org.mockito mockito-core ${mockito.core.version} test org.springframework spring-test ${spring.version} test import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.junit.Before; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.transaction.TransactionConfiguration; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.RequestBuilder; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.context.WebApplicationContext; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; /** * Created by zhengcanrui on 16/8/11. */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={"classpath:spring/applicationContext-*xml"}) //配置事务的回滚,对数据库的增删改都会回滚,便于测试用例的循环利用 @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true) @Transactional @WebAppConfiguration public class Test { //记得配置log4j.properties ,的命令行输出水平是debug protected Log logger= LogFactory.getLog(TestBase.class); protected MockMvc mockMvc; @Autowired protected WebApplicationContext wac; @Before() //这个方法在每个方法执行之前都会执行一遍 public void setup() { mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); //初始化MockMvc对象 } @org.junit.Test public void getAllCategoryTest() throws Exception { String responseString = mockMvc.perform( get("/categories/getAllCategory") //请求的url,请求的方法是get .contentType(MediaType.APPLICATION_FORM_URLENCODED) //数据的格式                .param("pcode","root") //添加参数 ).andExpect(status().isOk()) //返回的状态是200 .andDo(print()) //打印出请求和相应的内容 .andReturn().getResponse().getContentAsString(); //将相应的数据转换为字符串 System.out.println("--------返回的json = " + responseString); } }

Spring MVC的测试往往看似比较复杂。其实他的不同在于,他需要一个ServletContext来模拟我们的请求和响应。 @webappconfiguration是一级注释,用于声明一个ApplicationContext集成测试加载WebApplicationContext。作用是模拟ServletContext。

@ContextConfiguration:因为controller,component等都是使用注解,需要注解指定spring的配置文件,扫描相应的配置,将类初始化等。

perform:执行一个RequestBuilder请求,会自动执行SpringMVC的流程并映射到相应的控制器执行处理; get:声明发送一个get请求的方法。MockHttpServletRequestBuilder get(String urlTemplate, Object... urlVariables):根据uri模板和uri变量值得到一个GET请求方式的。另外提供了其他的请求的方法,如:post、put、delete等。 param:添加request的参数,如上面发送请求的时候带上了了pcode = root的参数。假如使用需要发送json数据格式的时将不能使用这种方式,可见后面被@ResponseBody注解参数的解决方法 andExpect:添加ResultMatcher验证规则,验证控制器执行完成后结果是否正确(对返回的数据进行的判断); andDo:添加ResultHandler结果处理器,比如调试时打印结果到控制台(对返回的数据进行的判断); andReturn:最后返回相应的MvcResult;然后进行自定义验证/进行下一步的异步处理(对返回的数据进行的判断);

写RESTful接口测试时需要注意返回的数据格式要标注成JSON : MediaType.APPLICATION_JSON

SoftInfo softInfo = new SoftInfo();       //设置值      ObjectMapper mapper = new ObjectMapper(); ObjectWriter ow = mapper.writer().withDefaultPrettyPrinter(); java.lang.String requestJson = ow.writeValueAsString(softInfo); String responseString = mockMvc.perform( post("/softs").contentType(MediaType.APPLICATION_JSON).content(requestJson)).andDo(print()) .andExpect(status().isOk()).andReturn().getResponse().getContentAsString(); 最后关于代码覆盖率

Intellij IDEA对这方面做了集成支持,右键运行测试代码

右键测试代码选择覆盖率测试

可以在包含有单元测试的代码中看到,绿色为已经覆盖的部分,红色未覆盖。

绿已覆盖,红未覆盖 Junit 5 未完待续


【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭