The Site
class is provided to me by an external team and has a private constructor.
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
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)
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!)
// 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.
For Mockito, there is no direct support to mock private and static methods. In order to test private methods, you will need to refactor the code to change the access to protected (or package) and you will have to avoid static/final methods.
0, we can now mock Java constructors with Mockito. This allows us to return a mock from every object construction for testing purposes. Similar to mocking static method calls with Mockito, we can define the scope of when to return a mock from a Java constructor for a particular Java class.
A private constructor is a special instance constructor. It is generally used in classes that contain static members only. If a class has one or more private constructors and no public constructors, other classes (except nested classes) cannot create instances of this class.
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:
// 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);
...
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With