vile在java是什么层,浅谈Java单元测试 - 让不可能变成可能,让可能变得简单,让简单变得优雅 - OSCHINA - 中文开源技术交流社区...

一、TDD(测试驱动开发(Test-Driven Development))

TDD是测试驱动开发(Test-Driven Development)的英文简称,是敏捷开发中的一项核心实践和技术,也是一种设计方法论。TDD的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码。TDD虽是敏捷方法的核心实践,但不只适用于XP(Extreme Programming),同样可以适用于其他开发方法和过程。

优缺点

优点:在任意一个开发节点都可以拿出一个可以使用,含少量bug并具一定功能和能够发布的产品。

缺点:增加代码量。测试代码是系统代码的两倍或更多,但是同时节省了调试程序及挑错时间。

二、Junit

JUnit是一个Java语言的单元测试框架,junit测试是程序员测试,即所谓白盒测试,因为程序员知道被测试的软件如何(How)完成功能和完成什么样(What)的功能。Junit是一套框架,继承TestCase类(junit4以前),就可以用Junit进行自动测试。

三、Junit常用注解

@Before:初始化方法

@After:释放资源

@Test:测试方法,在这里可以测试期望异常和超时时间(expected = Exception.class,timeout=5000)

@Ignore:忽略的测试方法

@BeforeClass:针对所有测试,只执行一次,且必须为static void

@AfterClass:针对所有测试,只执行一次,且必须为static void

@RunWith:指定使用的单元测试执行类

四、Junit测试用例执行顺序

**@BeforeClass ==> @Before ==> @Test ==> @After ==> @AfterClass**

过程:先加载模拟的环境,再进行测试。

五、基于spring boot 单元测试

1.添加依赖如下:

org.springframework.boot

spring-boot-starter-test

test

基于web应用单元测试

example:

@RunWith(SpringRunner.class)

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)

public class RandomPortExampleTests {

@Autowired

private TestRestTemplate restTemplate;

@Test

public void exampleTest() {

String body = this.restTemplate.getForObject("/", String.class);

assertThat(body).isEqualTo("Hello World");

}

}

3.基于jsonTest 单元测试

exmaple:

@RunWith(SpringRunner.class)

@JsonTest

public class MyJsonTests {

@Autowired

private JacksonTester json;

@Test

public void testSerialize() throws Exception {

VehicleDetails details = new VehicleDetails("Honda", "Civic");

// Assert against a `.json` file in the same package as the test

assertThat(this.json.write(details)).isEqualToJson("expected.json");

// Or use JSON path based assertions

assertThat(this.json.write(details)).hasJsonPathStringValue("@.make");

assertThat(this.json.write(details)).extractingJsonPathStringValue("@.make")

.isEqualTo("Honda");

}

@Test

public void testDeserialize() throws Exception {

String content = "{\"make\":\"Ford\",\"model\":\"Focus\"}";

assertThat(this.json.parse(content))

.isEqualTo(new VehicleDetails("Ford", "Focus"));

assertThat(this.json.parseObject(content).getMake()).isEqualTo("Ford");

}

}

4.基于MVC单元测试

example:

import org.junit.*;

import org.junit.runner.*;

import org.springframework.beans.factory.annotation.*;

import org.springframework.boot.test.autoconfigure.web.servlet.*;

import org.springframework.boot.test.mock.mockito.*;

import static org.assertj.core.api.Assertions.*;

import static org.mockito.BDDMockito.*;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;

import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@RunWith(SpringRunner.class)

@WebMvcTest(UserVehicleController.class)

public class MyControllerTests {

@Autowired

private MockMvc mvc;

@MockBean

private UserVehicleService userVehicleService;

@Test

public void testExample() throws Exception {

given(this.userVehicleService.getVehicleDetails("sboot"))

.willReturn(new VehicleDetails("Honda", "Civic"));

this.mvc.perform(get("/sboot/vehicle").accept(MediaType.TEXT_PLAIN))

.andExpect(status().isOk()).andExpect(content().string("Honda Civic"));

}

}

}

5.基于HTML5单元测试

example:

import com.gargoylesoftware.htmlunit.*;

import org.junit.*;

import org.junit.runner.*;

import org.springframework.beans.factory.annotation.*;

import org.springframework.boot.test.autoconfigure.web.servlet.*;

import org.springframework.boot.test.mock.mockito.*;

import static org.assertj.core.api.Assertions.*;

import static org.mockito.BDDMockito.*;

@RunWith(SpringRunner.class)

@WebMvcTest(UserVehicleController.class)

public class MyHtmlUnitTests {

@Autowired

private WebClient webClient;

@MockBean

private UserVehicleService userVehicleService;

@Test

public void testExample() throws Exception {

given(this.userVehicleService.getVehicleDetails("sboot"))

.willReturn(new VehicleDetails("Honda", "Civic"));

HtmlPage page = this.webClient.getPage("/sboot/vehicle.html");

assertThat(page.getBody().getTextContent()).isEqualTo("Honda Civic");

}

}

6.基于JDBC单元测试

example:

@RunWith(SpringRunner.class)

@JdbcTest

@Transactional(propagation = Propagation.NOT_SUPPORTED)

public class ExampleNonTransactionalTests {

}

7.基于MongoDB单元测试

example:

@RunWith(SpringRunner.class)

@DataMongoTest

public class ExampleDataMongoTests {

@Autowired

private MongoTemplate mongoTemplate;

}

example:

@RunWith(SpringRunner.class)

@DataMongoTest(excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class)

public class ExampleDataMongoNonEmbeddedTests {

}

8.基于rest client单元测试

example:

@RunWith(SpringRunner.class)

@RestClientTest(RemoteVehicleDetailsService.class)

public class ExampleRestClientTest {

@Autowired

private RemoteVehicleDetailsService service;

@Autowired

private MockRestServiceServer server;

@Test

public void getVehicleDetailsWhenResultIsSuccessShouldReturnDetails()

throws Exception {

this.server.expect(requestTo("/greet/details"))

.andRespond(withSuccess("hello", MediaType.TEXT_PLAIN));

String greeting = this.service.callRestService();

assertThat(greeting).isEqualTo("hello");

}

}

9.基于HTTP 的API接口测试

example:

@RunWith(SpringRunner.class)

@SpringApplicationConfiguration(classes = SpringBootSampleApplication.class)

//@WebAppConfiguration // 使用@WebIntegrationTest注解需要将@WebAppConfiguration注释掉

@WebIntegrationTest("server.port:0")// 使用0表示端口号随机,也可以具体指定如8888这样的固定端口

public class HelloControllerTest {

private String dateReg;

private Pattern pattern;

private RestTemplate template = new TestRestTemplate();

@Value("${local.server.port}")// 注入端口号

private int port;

@Test

public void test3(){

String url = "http://localhost:"+port+"/myspringboot/hello/info";

MultiValueMap map = new LinkedMultiValueMap();

map.add("name", "Tom");

map.add("name1", "Lily");

String result = template.postForObject(url, map, String.class);

System.out.println(result);

assertNotNull(result);

assertThat(result, Matchers.containsString("Tom"));

}

}

10.基于rest docs 单元测试

example:

@RunWith(SpringRunner.class)

@WebMvcTest(UserController.class)

@AutoConfigureRestDocs("target/generated-snippets")

public class UserDocumentationTests {

@Autowired

private MockMvc mvc;

@Test

public void listUsers() throws Exception {

this.mvc.perform(get("/users").accept(MediaType.TEXT_PLAIN))

.andExpect(status().isOk())

.andDo(document("list-users"));

}

}

以上为常见10种单元测试,实际编写时候可以根据业务来进行选择处理

六、参数化单元测试

Junit为我们提供的参数化测试需要使用 @RunWith(Parameterized.class) 然而因为Junit 使用@RunWith指定一个Runner,在我们更多情况下需要使用@RunWith(SpringRunner.class)来测试我们的Spring工程方法,所以我们使用assertArrayEquals 来对方法进行多种可能性测试便可。

example:

import static org.junit.Assert.assertTrue;

import java.util.Arrays;

import java.util.Collection;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.junit.runners.Parameterized;

import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)

public class ParameterTest {

private String name;

private boolean result;

/**

* 该构造方法的参数与下面@Parameters注解的方法中的Object数组中值的顺序对应

* @param name

* @param result

*/

public ParameterTest(String name, boolean result) {

super();

this.name = name;

this.result = result;

}

@Test

public void test() {

assertTrue(name.contains("小") == result);

}

@Parameters

public static Collection> data(){

// Object 数组中值的顺序注意要和上面的构造方法ParameterTest的参数对应

return Arrays.asList(new Object[][]{

{"小明2", true},

{"坏", false},

{"莉莉", false},

});

}

}

七、打包测试(自动化测试)

通常情况下我们写了5个测试类,我们需要一个一个执行。

打包测试,就是新增一个类,然后将我们写好的其他测试类配置在一起,然后直接运行这个类就达到同时运行其他几个测试的目的。

example:

@RunWith(Suite.class)

@SuiteClasses({ATest.class, BTest.class, CTest.class})

public class ABCSuite {

// 类中不需要编写代码

八、捕获与输出

使用 OutputCapture 来捕获指定方法开始执行以后的所有输出,包括System.out输出和Log日志。

OutputCapture 需要使用@Rule注解,并且实例化的对象需要使用public修饰

example:

public class MyTest {

@Rule

public OutputCapture capture = new OutputCapture();

@Test

public void testName() throws Exception {

System.out.println("Hello World!");

assertThat(capture.toString(), containsString("World"));

}

}

example:

@RunWith(SpringRunner.class)

@SpringBootApplication(classes = SpringBootSampleApplication.class)

//@WebAppConfiguration // 使用@WebIntegrationTest注解需要将@WebAppConfiguration注释掉

@WebIntegrationTest("server.port:0")// 使用0表示端口号随机,也可以具体指定如8888这样的固定端口

public class HelloControllerTest {

@Value("${local.server.port}")// 注入端口号

private int port;

private static final Logger logger = LoggerFactory.getLogger(StudentController.class);

@Rule

// 这里注意,使用@Rule注解必须要用public

public OutputCapture capture = new OutputCapture();

@Test

public void test4(){

System.out.println("HelloWorld");

logger.info("logo日志也会被capture捕获测试输出");

assertThat(capture.toString(), Matchers.containsString("World"));

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值