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
Mocking a private constructor
提问by Pranav Kapoor
The Site
class 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 Site
object. 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 id
and brand
only through getters, you could simply mock your class Site
then return this mock when you call the static method SiteUtil.getSite()
as next:
假设你的代码访问的价值id
和brand
只有通过干将,你可以简单地嘲笑你的类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.)
这样,对于测试,您可以注入自己的(模拟)策略,但不需要更改代码的现有客户端。(这也具有使查找本身更易于针对该组进行测试的优点。)