1, 在涉及到有 HTTP 发送请求的测试, 而所要访问的接口又没有准备好, 就需要用到 mockServer:
当一个测试类中有多个测试用例的时候, 必须使用 static. 测试发现, 测试类中不使用 static 的字段, 每个测试用例执行的时候都会创建新的对象, 会出现端口创建异常的情况, 即使使用了 mockServer.stop, 当 GET,POST 都测试的时候, 也会出现返回为空的情况 (端口冲突)
- // pom 文件
- org.mock-server</groupId>
- mockserver-netty</artifactId>
- 3.10.1</version>
- </dependency>
- import static org.mockserver.integration.ClientAndServer.startClientAndServer;
- import static org.mockserver.model.HttpRequest.request;
- import static org.mockserver.model.HttpResponse.response;
- import org.mockserver.integration.ClientAndServer;
- import org.mockserver.model.Header;
- import org.mockserver.model.HttpRequest;
- // 模拟的访问地址为: localhost:1002(端口自己指定)
- ClientAndServer mockServer = startClientAndServer(1002);
- // 防止有缓存的设置
- mockServer.reset();
- // 设置期望的返回结果
- String expected = "{\"success\":false,\"message\":\"success\"}";
- // 请求: 请求方式, 请求地址 (可加其他参数)
- HttpRequest request = request().withMethod("POST").withPath("/test");
- Header header = new Header("Content-Type", "application/JSON;charset=utf-8");
- mockServer.when(request).respond(response()
- .withStatusCode(200) // 表示响应成功
- .withBody(expected) // 响应体为期望值
- .withHeader(header)); // 响应数据的格式及编码
访问到该地址时返回的结果是预期设定的值.
2, 某些类在调用某个方法时, 想要让其返回想要的数据, 可以用 mock:
- import static org.mockito.Matchers.any;
- import static org.mockito.Mockito.doThrow;
- import static org.mockito.Mockito.mock;
- import static org.mockito.Mockito.reset;
- import static org.mockito.Mockito.when;
- eg:
- XxService abc = mock(XxService.class);
- // 1, 想让该实例调用方法时返回想要的结果
- UserService userService = mock(UserServiceImpl.class);
- when(userService.getCurUser()).thenReturn(user);
- ///2, 想让调用方法时抛出指定异常
- RedisUtil util = mock(RedisUtil.class);
- doThrow(Exception.class).when(util).publish(anyString(), anyString());
any() 表示调用方法的入参可以填任意值 ->
然后通过反射, 将 mock 出来的对象设置到指定的位置, 当执行到指定位置的时候, 对象调用所用的就是 mock 出来的对象, 调用的返回结果就是 thenReturn 的返回结果.
- Class<CustomerServiceImpl> cla = CustomerServiceImpl.class;
- Constructor<CustomerServiceImpl> cfon = cla.getConstructor();
- CustomerServiceImpl obj = cfon.newInstance();
- //
- Field field = cla.getDeclaredField("redisUtil");
- field.setAccessible(true);
- field.set(obj, util);
- // 通过反射调用方法
- Method method = cla.getMethod("setCustomerExtraData", Customer.class);
- boolean result = (boolean) method.invoke(obj, customer);
- // 保证 mock 的对象重新设置回原来的对象, 不然后继操作会受到影响
- reset(userService);
注意: 如果所测试的方法中有其他自动注入的对象, 也要在测试类里进行自动注入. 然后通过反射给他们设置进去, 不然会读取不到!
一些难以覆盖的地方都可以通过反射来进行测试.
3, 测试 Dao 层的时候, 可以用到 DBUnit, 主要用于测试前的数据准备, 以及测试后期望值对比:
- // pom 文件引入
- com.GitHub.springtestdbunit</groupId>
- spring-test-dbunit</artifactId>
- 1.3.0</version>
- test</scope>
- </dependency>
- org.dbunit</groupId>
- dbunit</artifactId>
- 2.5.3</version>
- test</scope>
- </dependency>
- // 类的监听
- @TestExecutionListeners({
- DependencyInjectionTestExecutionListener.class,
- DirtiesContextTestExecutionListener.class,
- TransactionalTestExecutionListener.class,
- DbUnitTestExecutionListener.class
- })
- @DbUnitConfiguration(dataSetLoader= XmlDataSetLoader.class)
准备数据 @DatabaseSetup(type = DatabaseOperation.INSERT,value = "classpath:/data/consumer.xml") 将需用用到的数据添加到 data 下 consumer.xml 文件中, 数据格式为:
- // 准备数据
- xml version="1.0" encoding="UTF-8"?>
- <tb_consumer id="[NULL]" name="Junit_consumer" type="2" address="Junit_address"
- contact_number="110" state="1" create_time="[NOW]" create_user_id="c0dc744d3aee11e892cb0025901bf22a" />
- <tb_consumer id="[UUID]" name="Junit_consumer2" type="2" address="[NULL]"
- contact_number="120" state="1" create_time="[NOW]" create_user_id="c0dc744d3aee11e892cb0025901bf22a" />
- <tb_consumer id="[UUID]" name="Junit_consumer2" type="[NULL]" address="Junit_address"
- contact_number="130" state="1" create_time="[NOW]" create_user_id="c0dc744d3aee11e892cb0025901bf22a" />
- <tb_consumer id="[UUID]" name="Junit_consumer2" type="2" address="Junit_address"
- contact_number="140" state="1" create_time="[NOW]" create_user_id="c0dc744d3aee11e892cb0025901bf22a" />
- <tb_consumer id="[UUID]" name="Junit_consumer2" type="2" address="Junit_address"
- contact_number="150" state="1" create_time="[NOW]" create_user_id="c0dc744d3aee11e892cb0025901bf22a" />
- </dataset>
dataset 节点下子节点为表名. 可以写入多张表, 属性为表的字段, 带 [] 字段为占位符 [UUID] 为 32 位 uuid,[NOW] 为当前时间,[NULL] 为 null.
- // 期望
- @ExpectedDatabase(table = "tb_consumer",query="select * from tb_consumer where name like'Junit%'", assertionMode = DatabaseAssertionMode.NON_STRICT_UNORDERED , value ="data/consumerExpect.xml")
期望文件 query 为期望文件与数据库中哪些数据对比, 如果不填将与数据库中所有数据对比, table 为表名, value 为期望文件, 填写期望数据, 当 assertionMode = DatabaseAssertionMode.NON_STRICT_UNORDERED 时, 没填的字段将不会对比
- // 期望数据
- xml version="1.0" encoding="UTF-8"?>
- <tb_consumer name="Junit_consumer2" type="2" address="[NULL]"
- contact_number="120" state="1" create_user_id="c0dc744d3aee11e892cb0025901bf22a" />
- <tb_consumer name="Junit_consumer" type="2" address="Junit_address"
- contact_number="110" state="1" create_user_id="c0dc744d3aee11e892cb0025901bf22a" />
- <tb_consumer name="Junit_consumer2" type="[NULL]" address="Junit_address"
- contact_number="130" state="1" create_user_id="c0dc744d3aee11e892cb0025901bf22a" />
- <tb_consumer name="Junit_consumer2" type="2" address="Junit_address"
- contact_number="140" state="1" create_user_id="c0dc744d3aee11e892cb0025901bf22a" />
- <tb_consumer name="Junit_consumer2" type="2" address="Junit_address"
- contact_number="150" state="1" create_user_id="c0dc744d3aee11e892cb0025901bf22a" />
- </dataset>
@Transactional 事物标签, 当方法执行完后, 数据库中的数据将回滚, 不会影响原有数据
- @SpringBootTest
- @RunWith(SpringJUnit4Cla***unner.class)
- @TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
- DirtiesContextTestExecutionListener.class,
- TransactionalTestExecutionListener.class,
- DbUnitTestExecutionListener.class })
- @DbUnitConfiguration(dataSetLoader= XmlDataSetLoader.class)
- public class ConsumerMapperDbUnitTest {
- @Autowired
- private ConsumerMapper consumerMapper;
- @Test
- @Transactional(rollbackFor = Exception.class)
- @DatabaseSetup(type = DatabaseOperation.INSERT, value = "data/consumer.xml")
- @ExpectedDatabase(table = "tb_consumer", query = "select * from tb_consumer where name like'Junit%'", assertionMode = DatabaseAssertionMode.NON_STRICT_UNORDERED,
- value = "data/consumerExpect.xml")
- public void testInsert() {
- List<Consumer> list = consumerMapper.selectAll();
- assertNotEquals(list.size(), 0);
- }
- }
来源: http://www.bubuko.com/infodetail-2803316.html