java 模拟私有构造函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39701670/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 04:34:55  来源:igfitidea点击:

Mocking a private constructor

javapowermockito

提问by Pranav Kapoor

The Siteclass is provided to me by an external team and has a privateconstructor.

Site课程由外部团队提供给我,有一个私人的构造函数。

public class Site
{
   int id;
   String brand;

   private Site(int id, String brand)
   {
      this.id = id;
      this.brand = brand;
   }
}

The SiteUtil class (controlled by team) is

SiteUtil 类(由团队控制)是

public class SiteUtil
{
   public static Site getSite()
   {
     Site site;
     //Logic
     return site; 
   }
 }

The data the getSite()function applies it logic on requires a network call, therefore it needs to be mocked. It doesn't have a setter currently (maybe to maintain consistency with the data source, not so sure)

getSite()函数应用其逻辑的数据需要网络调用,因此需要模拟。它目前没有设置器(可能是为了保持与数据源的一致性,不太确定)

I mock it as follows

我嘲笑它如下

Site mockSite = new Site(1,"Google");
PowerMockito.when(SiteUtil.getSite(1)).thenReturn(mockSite);

The code above of course dosent compile as I use the public constructor. The solution I read was to mock the private constructor of Siteobject. I'm however at a loss on how to do that (First time writing unit tests!)

当我使用公共构造函数时,上面的代码当然不会编译。我读到的解决方案是模拟Site对象的私有构造函数。然而,我不知道如何做到这一点(第一次编写单元测试!)

采纳答案by Nicolas Filotto

Assuming that your code accesses to the value of idand brandonly through getters, you could simply mock your class Sitethen return this mock when you call the static method SiteUtil.getSite()as next:

假设你的代码访问的价值idbrand只有通过干将,你可以简单地嘲笑你的类Site,然后当你调用静态方法返回这个模拟SiteUtil.getSite()的未来:

// Use the launcher of powermock
@RunWith(PowerMockRunner.class)
public class MyTestClass {

    @Test
    // Prepare the class for which we want to mock a static method
    @PrepareForTest(SiteUtil.class)
    public void myTest() throws Exception{
        // Build the mock of Site
        Site mockSite = PowerMockito.mock(Site.class);
        // Define the return values of the getters of our mock
        PowerMockito.when(mockSite.getId()).thenReturn(1);
        PowerMockito.when(mockSite.getBrand()).thenReturn("Google");
        // We use spy as we only want to mock one specific method otherwise
        // to mock all static methods use mockStatic instead
        PowerMockito.spy(SiteUtil.class);
        // Define the return value of our static method
        PowerMockito.when(SiteUtil.getSite()).thenReturn(mockSite);

        ...
    }
}

回答by chrylis -cautiouslyoptimistic-

As an alternate approach, there's a way to compatibly alter their API if you can get management to back you. Instead of hiding the network lookups in the getSite()method, externalize them into a SiteLookupStrategy:

作为替代方法,如果您可以得到管理层的支持,则有一种方法可以兼容地更改他们的 API。不要在getSite()方法中隐藏网络查找,而是将它们外部化为SiteLookupStrategy

public class SiteUtil {
    private static SiteLookupStrategy strategy = new DefaultSiteLookupStrategy();

    public static Site getSite(int siteNum) {
        return strategy.lookup(siteNum);
    }

    public static void setLookupStrategy(SiteLookupStrategy strategy) {
        SiteUtil.strategy = strategy;
    }
}

This way, for testing, you could inject your own (mocked) strategy, but existing clients of the code would not need to be changed. (This also has the advantage of making the lookup itself easier to test for that group.)

这样,对于测试,您可以注入自己的(模拟)策略,但不需要更改代码的现有客户端。(这也具有使查找本身更易于针对该组进行测试的优点。)