Giter Site home page Giter Site logo

Comments (7)

android10 avatar android10 commented on May 29, 2024

@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.

Jacksgong avatar Jacksgong commented on May 29, 2024

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.

android10 avatar android10 commented on May 29, 2024

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.

Jacksgong avatar Jacksgong commented on May 29, 2024

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.

android10 avatar android10 commented on May 29, 2024

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.

android10 avatar android10 commented on May 29, 2024

With that being said. If you need that functionality, unfortunately I have not found a way yet.

from android-kotlinintests.

Jacksgong avatar Jacksgong commented on May 29, 2024

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 photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.