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