Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test Coverage for DB call java code after couchbase 7.2 upgrade

We have recently upgraded Couchbase DB from 6.x to 7.2 . Which introduced collection and scope along with bucket. That means this

        GetResult serviceInventoryJsonDocument =      this.bucket.defaultCollection().get(this.getDocumentId(serviceInstanceId));

is replaced by

        GetResult serviceInventoryJsonDocument =
                      bucket.scope(bucketScope).collection(bucketCollection).get(getDocumentId(serviceInstanceId));

My Repository class is

    @Primary
    @Repository
    public class AccessServiceInventoryRepositoryImpl extends ServiceInventoryRepositoryImpl
        implements AccessServiceInventoryRepository {

    private final Logger log = LoggerFactory.getLogger(getClass());
    private final Gson gson = new Gson();
    private static final String CALL_BUCKET_REPLACE = "We are going to call bucket.replace";
    private static final String SELECT_FROM = "select * from ";

    @Autowired
    public AccessServiceInventoryRepositoryImpl(final ServiceInventoryMethodsValidator     serviceInventoryMethodsValidator,
            final CouchbaseConfigProperties couchbaseConfigProperties,
            final MicroserviceConfigProperties microserviceConfigProperties,
            final DomainServiceInventoryConfigProperties domainServiceInventoryConfigProperties) {
        super(serviceInventoryMethodsValidator, couchbaseConfigProperties,
                microserviceConfigProperties, domainServiceInventoryConfigProperties);
    }

    @Override
    public AccessServiceInventory getServiceInventoryById(final String serviceInstanceId)
            throws ServiceInventoryException {
        log.debug("{} retrieving service inventory by ID {}", getClass().getSimpleName(),
                getDocumentId(serviceInstanceId));
        final GetResult serviceInventoryJsonDocument =
                    bucket.scope(bucketScope).collection(bucketCollection).get(getDocumentId(serviceInstanceId));
        if (serviceInventoryJsonDocument == null) {
            throw new ServiceInventoryException("No results returned, processing timeout.");
        }
        return gson.fromJson(serviceInventoryJsonDocument.contentAsObject().toString(),      AccessServiceInventory.class);
    }
    }

My current junit test class is below

    @RunWith(MockitoJUnitRunner.class) @Ignore
    public class AccessServiceInventoryRepositoryImplTest {

    @Mock
    private Bucket bucket;
    @Mock
    private Cluster cluster;
    @Mock
    private Collection collectionBucket;
    @Mock
    private GetResult getResult;
    @Mock
    private QueryResult queryResult;
    @Mock
    private QueryMetaData queryMetaData;
    @Mock
    private ServiceInventoryMethodsValidator serviceInventoryMethodsValidator;
    private AccessServiceInventoryRepositoryImpl repositoryImpl;
    @Before
    public void setup() throws NoSuchFieldException, IllegalAccessException {

        repositoryImpl = new AccessServiceInventoryRepositoryImpl(
                serviceInventoryMethodsValidator,
                CouchbaseBucketConfig.getCouchbaseConfig(), CouchbaseBucketConfig.getMicroserviceConfigProperties(),
                new DomainServiceInventoryConfigProperties());
        ReflectionTestUtils.setField(repositoryImpl, "cluster", cluster);
        final Field bucketField = ServiceInventoryRepositoryImpl.class.getDeclaredField("bucket");
        bucketField.setAccessible(true);
        bucketField.set(repositoryImpl, bucket);
        when(bucket.defaultCollection()).thenReturn(collectionBucket);
        when(collectionBucket
                .get(anyString())).thenReturn(getResult);
    }

    @Test(expected = ServiceInventoryException.class)
    public void getServiceInventoryByIdShouldThrowServiceInventoryExceptionWhenJsonDocumentIsNull() throws     Exception {
        when(bucket.defaultCollection().get(anyString())).thenReturn(null);
        repositoryImpl.getServiceInventoryById("123456");
    }

I have tried changes test cases

when(bucket.defaultCollection().get(anyString())).thenReturn(null);

to

    when(bucket.scope(anyString())).thenReturn(scope);
        when(scope.collection(anyString())).thenReturn(collection);
        when(collection.get(anyString())).thenReturn(null);

but getting same exception

org.mockito.exceptions.base.MockitoException: 
Mockito cannot mock this class: class com.couchbase.client.java.Scope.
org.mockito.exceptions.base.MockitoException: 
Mockito cannot mock this class: class com.couchbase.client.java.Collection
Mockito can only mock non-private & non-final classes, but the root cause of this error might be different.

I have even made collection and scope as non private and non final in CouchbaseConfigProperties still getting same error I want this to work

like image 869
akshat rathore Avatar asked Jul 21 '26 18:07

akshat rathore


1 Answers

This is why some people (including the authors of Mockito!) suggest you should only mock types that you own.

You could address this issue by changing how and what you test. Changing the design of your application can also help.

At some point, you'll probably want tests that run against a real Couchbase Server cluster. I would highly recommend using TestContainers for this. It has a Couchbase module that works well.

On the application design side, you could create a little wrapper around the Couchbase Java SDK. Your wrapper could be an interface for easy mocking. Instead of mocking the classes and methods of the Couchbase SDK, you'd mock the methods of your wrapper.

I'd actually recommend the wrapper approach anyway, so you have a bulkhead against potential future changes to the Couchbase SDK API. In general, a wrapper also protects you against backend lock-in.

Disclaimer: I work at Couchbase.

like image 55
dnault Avatar answered Jul 24 '26 07:07

dnault



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!