0

I am trying to write junits for a provisioning service. The service eventually makes a call to a VICE Client and gets a certificate, This wastes certificate when the junits are run in testing to I wanted to mock this http call to the outside world.

The class structure looks something like this

class MyService {

    public void provisionTenant() {
        CLient client = generateCertificateClient(Some Params);
        client.enrollCertificate(enrollmentRequest);
    }

    //Private Method 1
    private generateCertificateCleint(Some Params) {
        return new CertClient(createSslContext(), endpoint);
    }

    //Private Method 2
    private createSslContext() {
        //Do something and return context
        return sslContext;
    }

}

// Second Class which is accessed using the new construct in the Service Class
class CertClient {

    private SSLContext;

    CertClient(SSLContext) {
        this.sslContext = ssslContext;
    }

    public enrollCertificate(enrollmentRequest) {
        final URL enrollUrl = asURL(serviceEndpointUrl, RequestType.ENROLL.value());
        executeRequest(enrollURL, enrollmentRequest, POST.value)
    }

    private byte[] executeRequest(final URL url, final Vice2Request request, final String httpMethod) {
        //Do a bunch of steps and return certificate s bytes
        HTTPConnection.writeOutPutStream();
        return getCerttificateAsBVytes(HTTPConnection);
    }

    //Return the Certificate fetched from the Generic POST call
    byte[] getCerttificateAsBytes(HTTPConnection connection) {
        try (InputStream inputStream = connection.getInputStream()) {
            return readBytes(inputStream, responseLength);
        }
    }
}

I have two challeges, One is that I am able to get 83% coverage for most code in both classes but If I mock the entire client class, I loose out on the code coverage.
Is there a way in which I can ,mock just the HTTPConnection post call in the second class i.e the client class, the client is not a Field in service, however I can refactor the code and make this a Field, but still it will be instantiated inside a method call via NEW, is there a way to mock this ?

I tried PowerMockito.whenNew by giving prepare for test Default CLient .class but that dosen't work, it always creates a new object. Second, how do I mock Service -> (Instantiates) Cleint -> (Intantiates) HttpConnection. How do I mock a variable two level down?

@Before
public void setUp() throws NoSuchFieldException {
    MockitoAnnotations.initMocks(this);
    ResponseBodyString = "<ResponseBOsy>"
}

 @Test
public void provisionKeyStoreTest() throws Exception {
    PowerMockito.mockStatic(SystemUtil.class);
    PowerMockito.when(SystemUtil.isStoreProvEnabled()).thenReturn(true);
    CertClient certClient = PowerMockito.mock(CertClient.class);
    PowerMockito.whenNew(CertClient.class).withAnyArguments().thenReturn(certClient);
SomeCaller.provisionTenant();
}
Sameer
  • 646
  • 1
  • 9
  • 27
  • 2
    This is exactly the reason to inject instead of using `new`. – chrylis -cautiouslyoptimistic- Jul 19 '19 at 08:45
  • You should post your test code as well. Also, you shouldn't be afraid of mocking because you loose code coverage, you simply have to write another test that actually test the CertClient. – Arnaud Claudel Jul 19 '19 at 08:53
  • 1
    Use [dependency injection](https://stackoverflow.com/questions/130794/what-is-dependency-injection) instead of a tool like Mockito. – Raedwald Jul 19 '19 at 10:57
  • This code should be refactored to be more SOLID. The difficulty in testing your code is a direct reflection of the quality of the design of the code under test. – Nkosi Jul 19 '19 at 11:43
  • You should improve your example code so that it actually compiles - especially the part with the connection. I can't really tell whether thats supposed to be a static method or just another typo. – second Jul 19 '19 at 12:58

0 Answers0