单元测试junit的使用

启动应用测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:consumer-test.xml"})
@FixMethodOrder(MethodSorters.NAME_ASCENDING)

https://www.cnblogs.com/bihanghang/p/10023759.html
https://blog.csdn.net/u012260238/article/details/87462366

mock启动应用mock测试在class上面添加如下即可:
@RunWith(MockitoJUnitRunner.Silent.class)

 

 

@RunWith(SpringJUnit4ClassRunner.class)
@SpringJUnitConfig(Application.class)
@TestPropertySource(locations = "classpath:application.properties")
@Slf4j
public class CalculatorTest {

 private MockMvc mvc;

    @Before
    public void setUp() throws Exception {
        mvc = MockMvcBuilders.webAppContextSetup(wac).build();  //初始化MockMvc对象
    }

    @Test
    public void calculate() {
        assertEquals(3, new Calculator().calculate("1 + 2"));
        assertEquals(3, new Calculator().calculate("1 + 2 + 3"));
    }
}
参数说明:
@SpringJUnitConfig(Application.class) 配置Spring中的测试环境
@BeforeClass 全局只会执行一次,而且是第一个运行
@Before 在测试方法运行之前运行
@Test 测试方法
@After 在测试方法运行之后允许
@AfterClass 全局只会执行一次,而且是最后一个运行
@Ignore 忽略此方法
@ConsumerLocations("consumer.xml")在dubbo单元测试中用到,配置消费者xml
@TestPropertySource(locations = "classpath:application.properties")配置xml配置文件
@RunWith(SpringJUnit4ClassRunner.class) 让测试在Spring容器环境下执行
@ContextConfiguration(Locations="../*.xml") 用于指定配置文件所在的位置

@RunWith 使用RunWith注解改变JUnit的默认执行类,并实现自已的Listener在平时的单元测试,如果不使用RunWith注解,那么JUnit将会采用默认的执行类Suite执行。
@ContextConfiguration 可以通过该属性手工指定 Spring 配置文件所在的位置,可以指定一个或多个 Spring 配置文件。

以上就是我们的单元测试,需要遵循一下规则:

1、每一个测试方法上使用@Test进行修饰

2、每一个测试方法必须使用public void 进行修饰

3、每一个测试方法不能携带参数

4、测试代码和源代码在两个不同的项目路径下

5、测试类的包应该和被测试类保持一致

6、测试单元中的每个方法必须可以独立测试

3、mock
什么是mock
单元测试:设置测试数据,设定预期结果,验证结果。mock就是创建某类型的虚拟对象,进行模拟操作。
<dependency>

            <groupId>junit</groupId>

            <artifactId>junit</artifactId>

            <version>4.11</version>

            <!--表示开发的时候引入,发布的时候不会加载此包 -->

            <scope>test</scope>

        </dependency>

        <dependency>

            <groupId>org.mockito</groupId>

            <artifactId>mockito-all</artifactId>

            <version>1.9.5</version>

            <scope>test</scope>

</dependency>
<configuration>
                    <!-- 是否跳过测试 -->
                    <skipTests>false</skipTests>
                    <!-- 排除测试类 -->
                    <excludes>
                        <exclude>**/Base*</exclude>
                    </excludes>
                </configuration>

以下是用例:
public class PersonServiceTest {  
  
    @Mock  
    private PersonDao personDAO;  // 模拟对象  
    private PersonService personService;  // 被测类  
  
    public PersonServiceTest() {  
    }  
  
    @BeforeClass  
    public static void setUpClass() {  
    }  
  
    @AfterClass  
    public static void tearDownClass() {  
    }  
  
    // 在@Test标注的测试方法之前运行  
    @Before  
    public void setUp() throws Exception {  
        // 初始化测试用例类中由Mockito的注解标注的所有模拟对象  
        MockitoAnnotations.initMocks(this);  
        // 用模拟对象创建被测类对象  
        personService = new PersonService(personDAO);  
    }  
  
    //@Ater是在每个测试方法运行完毕后均执行一次
    @After  
    public void tearDown() {  
    }  
  
    @Test  
    public void shouldUpdatePersonName() {  
        Person person = new Person(1, "Phillip");  
        // 设置模拟对象的返回预期值  
        when(personDAO.fetchPerson(1)).thenReturn(person);  
        // 执行测试  
        boolean updated = personService.update(1, "David");  
        // 验证更新是否成功  
        assertTrue(updated);  
        // 验证模拟对象的fetchPerson(1)方法是否被调用了一次  
        verify(personDAO).fetchPerson(1);  
        // 得到一个抓取器  
        ArgumentCaptor<Person> personCaptor = ArgumentCaptor.forClass(Person.class);  
        // 验证模拟对象的update()是否被调用一次,并抓取调用时传入的参数值  
        verify(personDAO).update(personCaptor.capture());  
        // 获取抓取到的参数值  
        Person updatePerson = personCaptor.getValue();  
        // 验证调用时的参数值  
        assertEquals("David", updatePerson.getPersonName());  
        // asserts that during the test, there are no other calls to the mock object.  
        // 检查模拟对象上是否还有未验证的交互  
        verifyNoMoreInteractions(personDAO);  
    }  
  
    @Test  
    public void shouldNotUpdateIfPersonNotFound() {  
        // 设置模拟对象的返回预期值  
        when(personDAO.fetchPerson(1)).thenReturn(null);  
        // 执行测试  
        boolean updated = personService.update(1, "David");  
        // 验证更新是否失败  
        assertFalse(updated);  
        // 验证模拟对象的fetchPerson(1)方法是否被调用了一次  
        verify(personDAO).fetchPerson(1);  
        // 验证模拟对象是否没有发生任何交互  
        verifyZeroInteractions(personDAO);  
        // 检查模拟对象上是否还有未验证的交互  
        verifyNoMoreInteractions(personDAO);  
    }      
  
    /** 
     * Test of update method, of class PersonService. 
     */  
    @Test  
    public void testUpdate() {  
        System.out.println("update");  
        Integer personId = null;  
        String name = "Phillip";  
        PersonService instance = new PersonService(new PersonDao() {  
  
            @Override  
            public Person fetchPerson(Integer personID) {  
                System.out.println("Not supported yet.");  
                return null;  
            }  
  
            @Override  
            public void update(Person person) {  
                System.out.println("Not supported yet.");  
            }  
        });  
        boolean expResult = false;  
        boolean result = instance.update(personId, name);  
        assertEquals(expResult, result);  
        // TODO review the generated test code and remove the default call to fail.  
        fail("The test case is a prototype.");  
    }  
}     

 

也可只使用

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class NativeTest {}

 

 

用例如下:

 

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class NativeTest {
//需要模拟的对象
@Mock
UserServiceImpl userService;
//需要测试的类
@InjectMocks
LoginServiceImpl loginServiceImpl

@Test  
  public void shouldNotUpdateIfPersonNotFound() {  
        // 设置模拟对象的返回预期值  
        when(userService.fetchPerson(1)).thenReturn(null);  
        // 执行测试  
        boolean updated = oginServiceImpl.login(1, "David");  
        // 验证更新是否失败  
        assertFalse(updated);  
        // 验证模拟对象的fetchPerson(1)方法是否被调用了一次  
        verify(personDAO).fetchPerson(1);  
        // 验证模拟对象是否没有发生任何交互  
        verifyZeroInteractions(personDAO);  
        // 检查模拟对象上是否还有未验证的交互  
        verifyNoMoreInteractions(personDAO);  
        // 检查模拟对象上是否没有调用
         verify(userService, never()).fetchPerson(any());
        
          verify(userService, times(2)).getUserInfoByMobile(any());
          verify(userService, never()).fetchPerson(any());
          //调到时不进行处理,只有返回void的方法可用
         doNothing().when(jmqProducer).sendMessage(any(),anyString(),anyString());
        Mockito.when(userService.cfetchPerson(anyString(), any())).thenReturn(new User());
        verify(jmqProducer, never()).sendMessage(any(),anyString(),anyString());//never代表方法调用0次
        //调用两次
        verify(oginServiceImpl, times(2)).login(anyString(),any());
        Assert.assertEquals(userDto.getName(),1);
        //异常测试
 try {
        oginServiceImpl.login(null);
        } catch (Exception e) {
            Assert.assertTrue(e instanceof BusinessException);
        }
thrown.expect(BusinessException.class);
    }      
}

当单元测试中需要moke掉类中@Value注解时可用

ReflectionTestUtils.setField(userServiceImpl, "sourceType", "es");

在@Before中添加其中userServiceImpl为@InjectMocks需要测试的类,sourceType为@Value的参数es为moke的值。

安装TestMe插件之后再类上面点击alt+insert键可快速生成mock的test方法

可在测试类上面添加

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:consumer-test.xml"})
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Slf4j

或者使用如下也可以用如下完整实例:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = TestApplication.class)
public class CollectOptConsumerTest {

    @Resource
    private CollectOptConsumer collectOptConsumer;

    @Test
    public void execute() {
        String text = "{\"operateTime\":1615026212069}";
        collectOptConsumer.execute(text);
    }
}

@SpringBootApplication
@PropertySource(value = {
        "classpath:META-INF/config/producer.properties",
        "classpath:META-INF/config/jconsumer.properties",
        "classpath:META-INF/config/message.properties",
        "classpath:META-INF/config/jdbcp.properties"

})
@ImportResource(value = {
        "classpath:META-INF/spring/jmq-producer.xml",
        "classpath:META-INF/spring/jmq-consumer.xml",
        "classpath:META-INF/spring/spring-consumer.xml",
        "classpath:META-INF/spring/applicationContext.xml",
        "classpath:META-INF/spring/spring.xml",
        "classpath:META-INF/spring/spring-es.xml",
        "classpath:META-INF/spring/single-datasource-test.xml",
        "classpath:META-INF/spring/spring-config.xml",
        "classpath:META-INF/spring/spring-jss.xml",
//        "classpath:META-INF/spring/sharding-datasource.xml",
        "classpath:META-INF/spring/spring-es.xml"
})

@MapperScan({"com.test.activity.recybag.dao","com.test.activity.dao.*"})
public class TestApplication extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(TestApplication.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }
}

 

https://blog.csdn.net/g5628907/article/details/79078134

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值