让我们看看需要测试的代码:
public class DemoCodeCoverage {
public void showDemo(LibraryCode library) {
System.out.println("Hello World!");
library.runDemoApplication();
// Extract the below code to a method since LibraryCode is not passed
// Then ignore running that method
// LibraryCode library = new LibraryCode()
// library.runDemoApplication_1();
// library.runDemoApplication_2();
// library.runDemoApplication_3();
System.out.println("World ends here!");
}
public boolean showBranchingDemo(boolean signal) {
if (signal) {
signalShown();
} else {
noSignal();
}
return signal;
}
public void signalShown() {
System.out.println("signalShown!");
}
public void noSignal() {
System.out.println("NoSignal!");
}
}
public class LibraryCode {
// Library can be AWS/Database code which needs authentication
// And this authentication is not a concern for our UT
// Still will end up execption when we do our UT
public void runDemoApplication() {
throw new RuntimeException();
}
}
下面可以给出很好的代码覆盖率:
public class DemoCodeCoverageTest {
@Test
public void testShowDemo() {
DemoCodeCoverage t = Mockito.spy(new DemoCodeCoverage());
LibraryCode lib = Mockito.mock(LibraryCode.class);
Mockito.doNothing().when(lib).runDemoApplication();
t.showDemo(lib);
// when(bloMock.doSomeStuff()).thenReturn(1);
// doReturn(1).when(bloMock).doSomeStuff();
}
@Test
public void testShowBranchingDemo() {
DemoCodeCoverage t = Mockito.spy(new DemoCodeCoverage());
assertEquals(true, t.showBranchingDemo(true));
assertEquals(false, t.showBranchingDemo(false));
}
@Test
public void testSignalShown() {
DemoCodeCoverage t = Mockito.spy(new DemoCodeCoverage());
t.showBranchingDemo(true);
Mockito.verify(t, times(1)).signalShown();
}
@Test
public void testNoSignal() {
DemoCodeCoverage t = Mockito.spy(new DemoCodeCoverage());
t.showBranchingDemo(false);
Mockito.verify(t, times(1)).noSignal();
}
}
以下是增加测试代码覆盖率的步骤:
案例_1:测试void方法
假设您有一个不带任何参数且不返回任何内容的方法。
public void printHelloWorld() {
System.out.println("Hello World")
}
您仍然可以编写调用此方法并成功返回而没有任何 runtimeException 的测试。
实际上,除了提供通过我们的测试运行代码的选项之外,我们还没有在这里测试任何东西。从而增加代码覆盖率。
此外,您可以验证调用:
Mockito.verify(instance, times(1)).printHelloWorld();
有些情况你不能测试,比如第三方库调用,那么库可能已经测试过了,我们只需要跑一遍。
@Test
public void testPrintHelloWorld() {
// may be hibernate call/other 3rd party method call
instance.printHelloWorld();
}
如果你的工具对 100% 的代码覆盖率不严格,你甚至可以忽略它并证明它是合理的。
Case_2:使用在测试方法中创建并调用另一个方法的对象测试方法
假设您有方法调用 DB 以在 Hello_World 表中添加条目也将其打印在控制台中,如下所示。
public void printHelloWorld() throws DBException {
DBConnection db = new DBConnection();
db.createEntry(TABLE_NAME, "Hello World");
System.out.println("Hello World")
}
您可以将这些数据库代码提取到新方法中,然后单独测试。
public void printHelloWorld() throws DBException {
makeHelloWorldEntryInTable();
System.out.println("Hello World")
}
public void makeHelloWorldEntryInTable() throws DBException {
DBConnection db = new DBConnection();
db.createEntry(TABLE_NAME, "Hello World");
}
在使用 DB 进行测试时,您会期望 DBConnectionException,因为它只是单元测试。因此,使用@Test(expected=DBException) 对makeHelloWorldEntryInTable 进行一项测试,并在printHelloWorld() 上进行另一项测试,并跳过方法makeHelloWorldEntryInTable 调用,如下所示。从而增加代码覆盖率。
@Test(expected=DBException)
public void testMakeHelloWorldEntryInTable() {
//This can any third party library which cannot be configured for ut.
//One example is testing the AWS bucket exist or not.
instance.makeHelloWorldEntryInTable();
}
@Test
public void testPrintHelloWorld() {
Mockito.doNothing()
.when(localInstance)
.makeHelloWorldEntryInTable();
localInstance.printHelloWorld();
}
Case_3:如果您有私有方法,则将其设为默认包级别并对其进行测试。从而提高代码覆盖率。