Junit

作者: kk爱自由 | 来源:发表于2022-11-17 13:51 被阅读0次

    通常 Java 中的 Junit 会使用到 mockito 框架,详情可以参考之前专门介绍 Mocktio的博文 .
    本文记录 Junit框架下的一些实现方式和解决问题的思路:

    @RunWith

    Parameterized.class

    参数化测试伪代码:

    @RunWith(Parameterized.class)
    public class ParameterizedTestDemo {
      // 初始化 mockito,由于RunWith 已经使用了Parameterized,所以要让 mock 生效可以采用MockitoRule
      @Rule
      public MockitoRule rule = MockitoJUnit.rule(); 
    
      @Mock
      private StateRepository serviceRepo;
      @InjectMock
      private StateService service;
    
    // 需要参数化测试的参数
      private Integer param;
      private EnmuClass state;
    
    // 构造方法,本质是为了每一组参数创建测试类实例
      public ParameterizedTestDemo(Integer param, EnmuClass state) {
            this.param = param;
            this.state = state;
      }
    // 静态方法,必须返回一个集合。提供测试的具体参数列表,可以在注解中使用 name = {index} 为每组测试提供名称,便于区分
        @Parameterized.Parameters(name = "{1}")
        public static Collection<Object[]> params() {
            return newArrayList(new Object[]{1, EnmuClass.STATE1}, new Object[]{2, EnmuClass.STATE2});
        }
    
        @Test
        public void testParameterized() {
              // given
              doReturn(..).when(service).invokeSomeMethod();
              // when
              service.invokeServiceMethod(param, state);
              // then
              assertThat(...);
        }
    }
    

    MockitoJUnitRunner.class

    用于初始化 mockito 使@Mock @Spy @InjectMock 等 mockito 注解生效,等价于在 before 方法中调用MockitoAnnotations.openMocks(this); 方法


    其他一些常用的第三方 runner: Custom runners

    @Rule

    用于灵活的增加或重定义每个测试方法的行为。Junit4 内置了一些 rules
    ExpectedException:异常测试,类似于@Test(expected = xxxException.class)

    public static class HasExpectedException {
      @Rule
      public final ExpectedException thrown = ExpectedException.none();
    
      @Test
      public void throwsNothing() {
    
      }
    
      @Test
      public void throwsNullPointerException() {
        thrown.expect(NullPointerException.class);
        throw new NullPointerException();
      }
    
      @Test
      public void throwsNullPointerExceptionWithMessage() {
        thrown.expect(NullPointerException.class);
        thrown.expectMessage("happened?");
        thrown.expectMessage(startsWith("What"));
        throw new NullPointerException("What happened?");
      }
    }
    

    ExternalResource:用于在测试前设置了一个外部资源(文件、socket、server、数据库连接等),并保证在测试后将其关闭。

    public static class UsesExternalResource {
      Server myServer = new Server();
      
      @Rule
      public final ExternalResource resource = new ExternalResource() {
        @Override
        protected void before() throws Throwable {
          myServer.connect();
        };
        
        @Override
        protected void after() {
          myServer.disconnect();
        };
      };
      
      @Test
      public void testFoo() {
        new Client().run(myServer);
      }
    }
    

    TemporaryFolder:用于创建文件与目录并且在测试运行结束后将其删除。

    public static class HasTempFolder {
      @Rule
      public final TemporaryFolder folder = new TemporaryFolder();
    
      @Test
      public void testUsingTempFolder() throws IOException {
        File createdFile = folder.newFile("myfile.txt");
        File createdFolder = folder.newFolder("subfolder");
        // ...
      }
    } 
    

    TestName:在测试中获取当前测试方法的名称。

    public class NameRuleTest {
      @Rule
      public final TestName name = new TestName();
      
      @Test
      public void testA() {
        assertEquals("testA", name.getMethodName());
      }
      
      @Test
      public void testB() {
        assertEquals("testB", name.getMethodName());
      }
    }
    

    TestWatcher:提供五个触发点:测试开始、测试完成、测试成功、测试跳过、测试失败,允许我们在每个触发点执行自定义的逻辑。 例如如下在每个触发点连续记录 log

    public class WatchmanTest {
      private static String watchedLog;
    
      @Rule
      public final TestRule watchman = new TestWatcher() {
        @Override
        public Statement apply(Statement base, Description description) {
          return super.apply(base, description);
        }
    
        @Override
        protected void succeeded(Description description) {
          watchedLog += description.getDisplayName() + " " + "success!\n";
        }
    
        @Override
        protected void failed(Throwable e, Description description) {
          watchedLog += description.getDisplayName() + " " + e.getClass().getSimpleName() + "\n";
        }
    
        @Override
        protected void skipped(AssumptionViolatedException e, Description description) {
          watchedLog += description.getDisplayName() + " " + e.getClass().getSimpleName() + "\n";
        }
    
        @Override
        protected void starting(Description description) {
          super.starting(description);
        }
    
        @Override
        protected void finished(Description description) {
          super.finished(description);
        }
      };
    
      @Test
      public void fails() {
        fail();
      }
    
      @Test
      public void succeeds() {
      }
    }
    

    Timeout:支持为测试类中的所有测试方法设置相同的超时时间,类似于@Test(timeout = 100)


    除此以为,还有第三方 rule 实现或者自己实现 TestRule,MethodRule接口
    例如 MockitoRule 用来初始化 mockito

    相关文章

      网友评论

          本文标题:Junit

          本文链接:https://www.haomeiwen.com/subject/hnyyxdtx.html