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