Comments (7)
@Jacksgong no apologies! This is actually the best place to have discussions.
I have got a question then...why do you want to test or mock a static class? Can you give more details on that?
When I see that I cannot mock collaborators, I prefer to think that there is a problem with my code and not with the mocking framework...that is why I want to understand your use case.
from android-kotlinintests.
Thanks for your response, that is why Powermock support mock static
class or method.
One normal case I have occurred is I write a unit test for NetworkEngine
and all real network operations is warped in the NetworkUtil
. Such as:
NetworkEngine
:
class NetworkEngine {
...
@Override
public boolean upload(byte[] bytes) {
final StamperConfig config = Stamper.get().getConfig();
if (!config.isReady()) {
StamperDebug.d(NetworkEngine.class, "require to upload bytes[%d], but config not ready yet",
bytes.length);
return false;
}
final String url = config.getRequestUrl();
// upload to backend
final int status = NetworkUtil.post(url, bytes);
final boolean success = status >= 200 && status < 300;
if (!success) {
final String errorUrl = String.format(Locale.ENGLISH,
"%s?app_name=%s&uid=%s&status=%d&app_version=%s",
config.getErrorReportUrl(),
config.getAppName(),
config.getUserId(),
status,
mVersionCode);
NetworkUtil.getIgnoreResponse(errorUrl, config.getUserAgent());
StamperDebug.d(NetworkEngine.class, "failed upload bytes[%d], upload to error server, %d",
bytes.length, status);
} else {
StamperDebug.d(NetworkEngine.class, "success upload bytes[%d]", bytes.length);
}
return success;
}
...
}
NetworkEngineTest
:
and my unit test for NetworkEngine#upload
need to mock the NetworkUtil
class which is the static
class:
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertFalse;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.verifyStatic;
/**
* Created by Jacksgong on 18/10/2016.
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest(NetworkUtil.class)
public class NetworkEngineImplTest {
private NetworkEngine mNetworkEngine;
private final static byte[] MOCK_BYTES = "mock-bytes".getBytes();
@BeforeClass
public static void setUpClass() {
StamperMocksHelper.mockStamperWithEmptyConfig();
}
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mockStatic(NetworkUtil.class);
mNetworkEngine = new NetworkEngineImpl();
}
@After
public void tearDown() {
mNetworkEngine.shutdown();
}
@Test
public void upload_configNotReady_returnFalse() {
when(getStamperConfig().isReady()).thenReturn(false);
assertFalse(mNetworkEngine.upload(MOCK_BYTES));
verifyStatic(times(0));
NetworkUtil.post(anyString(), anyByteArray());
verifyStatic(times(0));
NetworkUtil.getIgnoreResponse(anyString(), anyString());
}
@Test
public void upload_200Response_returnTrue() {
when(getStamperConfig().isReady()).thenReturn(true);
when(NetworkUtil.post(Mockito.anyString(), anyByteArray())).thenReturn(200);
assertThat(mNetworkEngine.upload(MOCK_BYTES)).isTrue();
verifyStatic();
NetworkUtil.post(anyString(), anyByteArray());
}
@Test
public void upload_failedResponse_reportToErrorServer() {
when(getStamperConfig().isReady()).thenReturn(true);
when(NetworkUtil.post(anyString(), anyByteArray())).thenReturn(500);
assertFalse(mNetworkEngine.upload(MOCK_BYTES));
verifyStatic();
NetworkUtil.post(anyString(), anyByteArray());
verifyStatic();
NetworkUtil.getIgnoreResponse(anyString(), anyString());
}
private StamperConfig getStamperConfig() {
return Stamper.get().getConfig();
}
}
from android-kotlinintests.
In that case I would not use a static class. I would pass it as a collaborator to your NetworkEngine.java
(and if you want only one instance, just use a singleton).
Also I might need more context but it looks like your utils does many things. It handles errors for example, which I would extract to an error manager or something like that.
I do not see many reasons to have a static class here. For strings is fine I would say.
from android-kotlinintests.
Sorry, This is just the sample code snippet for covering what you want, you can not deny there are many other static
classes like Util
do, we need to mock it, because we don't want them to affect the function what we are testing for.
And I think it is no neccessary to discuss about whether we need to mock the static
class and method or not, because even if it is a few cases, That is still a problem we need to face to in our actual programing. We need to simplify such case like powermock do(there are many people use powermock to mock static
method or class), though we really can mock the static
class or method through the most original way used in Java: wrapper a non-static
class or method for the static
one, then mock the non-static
one.
from android-kotlinintests.
And I think it is no neccessary to discuss about whether we need to mock the static class and method or not, because even if it is a few cases, That is still a problem we need to face to in our actual programing. We need to simplify such case like powermock do(there are many people use powermock to mock static method or class), though we really can mock the static class or method through the most original way used in Java: wrapper a non-static class or method for the static one, then mock the non-static one.
Well, that is the thing...I do not have those problems because I do not need to mock any static methods (and in my opinion when that happens, the problem is in your code, and by the way, powermock is a hack). And if there is any of those static methods in a third-party library I just wrapped them in my own class and pass it as a collaborator.
from android-kotlinintests.
With that being said. If you need that functionality, unfortunately I have not found a way yet.
from android-kotlinintests.
Okay, I get your point, actually, I agree your solution really works sometimes when it's the architecture matter. thanks for your advice, thanks anyway.
from android-kotlinintests.
Related Issues (1)
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from android-kotlinintests.