使用静态类进行测试既可以操作也可以不操作

时间:2017-12-13 08:16:42

标签: java junit mockito powermock

我正在尝试运行Powermock测试,有两种测试方法。 第一种方法是正常测试,不需要嘲笑任何东西,并且可以独立工作。 第二种方法使用PowerMockito.mockStatic(InetAddress.class) - 它操作主机地址,并且单独工作。 当我同时运行两个测试时,其中一个方法失败,具体取决于先运行哪个。第一种测试方法总是成功,第二种测试方法失败。

如何避免此问题?

@RunWith(PowerMockRunner.class)
@PrepareForTest(ClassForTest.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class TestForClassForTest{

    @Test
    public void test_is_ok() throws Exception {
        boolean internalLogging = ClassForTest.allowInternalLogging();
        Assert.assertTrue(internalLogging);
    }

    @Test
    public void test_nok() throws Exception {
      PowerMockito.mockStatic(InetAddress.class);
      PowerMockito.when(InetAddress.getLocalHost()).thenReturn(inetAddress);
      when(inetAddress.getHostAddress()).thenReturn("1.1.1.1");

      boolean internalLogging = ClassForTest.allowInternalLogging();
      Assert.assertFalse(internalLogging);
   }
}

方法" allowInternalLogging"使用InetAddress.getByName(" domain")确定是否"域"可从当前网络访问:

public final class ClassForTest {

    private static Boolean internalLogging;

    private ClassForTest() {
    }


    private static boolean inNetwork() {
        // By default no hosts should be found!
        boolean hostFound = false;

        try {
            // "Ping" the hosts by looking up the inetaddress
            final InetAddress address = InetAddress.getByName("some-hostname-which-we-know");

           // If the address is not null, we were able to lookup the
           // specified hostname.
           if (address != null) {
              hostFound = true;
           }

        } catch (final UnknownHostException ex) {
           // Host could not be found!
           hostFound = false;
        }

        return hostFound;
    }


    public static Boolean allowInternalLogging() {
        if (internalLogging == null) {
            try {
                internalLogging = inNetwork();
            } catch (Exception e) {
                internalLogging = false;
                LOGGER.debug("Could not determine logging granularity", e);
            }
        }
        return internalLogging;
    }
}

1 个答案:

答案 0 :(得分:1)

import { Compiler, Component, Injector, VERSION, ViewChild, NgModule, NgModuleRef, OnInit, ViewContainerRef } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { RouterModule } from '@angular/router'; import { CmsService } from "../../services/cms.service"; @Component({ selector: 'home-page', template: ` <ng-container #vc></ng-container> ` }) export class HomePageComponent implements OnInit { constructor(private _compiler: Compiler, private _injector: Injector, private _m: NgModuleRef<any>) { } ngOnInit() { } @ViewChild('vc', { read: ViewContainerRef }) vc; ngAfterViewInit() { const tmpCmp = Component({ moduleId: module.id, templateUrl: '../../../assets/HomePage/home-page-rbu.component.html' })( class { constructor(public cms: CmsService) { } welcomeTXT: string; advertismentTXT: string; ngOnInit() { this.cms.getCMSItemValue('welcomeTXT').subscribe(res => { this.welcomeTXT = res; }); this.cms.getCMSItemValue('advertismentTXT').subscribe(res => { this.advertismentTXT = res; }); } }); @NgModule({ imports: [BrowserModule, RouterModule], declarations: [tmpCmp], providers: [CmsService] }) class DynamicModule { } this._compiler.compileModuleAndAllComponentsAsync(DynamicModule) .then((factories) => { const f = factories.componentFactories[0]; const cmpRef = f.create(this._injector, [], null, this._m); cmpRef.instance.name = 'dynamic'; this.vc.insert(cmpRef.hostView); }) } }

的实施
ClassForTest

此方法有效地缓存public static Boolean allowInternalLogging() { if (internalLogging == null) { try { internalLogging = inNetwork(); } catch (Exception e) { internalLogging = false; LOGGER.debug("Could not determine logging granularity", e); } } return internalLogging; } 的结果,这会导致任何后续调用重用第一次调用产生的结果。

  • 如果首先调用inNetwork,则会导致test_nok设置为ClassForTest.internalLogging,从而导致false失败,因为它需要test_is_ok
  • 如果首先调用true,则会导致test_is_ok设置为ClassForTest.internalLogging,从而导致true失败,因为它需要test_nok

如果需要多次调用此方法并期望得到不同的结果,则必须在每次调用之间重置false或以某种方式参数化ClassForTest.internalLogging方法,以便它可以选择绕过缓存值。

FWIW,我使用您提供的代码重现了该问题,然后在allowInternalLogging内禁用了缓存,并重新运行了他们通过的两个测试。

注意:allowInternalLogging()方法会在inNetworkInetAddress上进行此次调用,但您提供的测试用例需要InetAddress.getByName("some-hostname-which-we-know");,因此不匹配测试用例和被测代码。