1

I'm trying to write unit test (using fflib framework) for a piece of functionality where on insertion of an object files are created.

This is the main piece of code i'm trying to cover:

fflib_ISObjectUnitOfWork uow = App_Application.unitOfWork.newInstance();
List<ContentVersion> cVerFileLst = new List<ContentVersion>();
Set<Id> cVerIdSet = new Set<Id>();

for(Id recordId :recordIds) {
  // Add content version record
  ContentVersion cVerFile = new ContentVersion();
  cVerFile.VersionData = Blob.valueOf('Test'); 
  cVerFile.Title = 'File TEST';
  cVerFile.ContentLocation= 'S';
  cVerFile.PathOnClient = 'Test Name' + '.' + 'pdf';
  cVerFileLst.add(cVerFile);
}
uow.registerNew(cVerFileLst);
uow.commitWork();

for(ContentVersion cVer : cVerFileLst){
   cVerIdSet.add(cVer.Id);
}

system.debug(cVerIdSet); //this prints empty when ran from test class

//... Logic to query Content Version again (with Id in cVerIdSet) and get ContentDocumentId which is 
used for creating Content Document Link

The functionality works fine on UI but the problem is on test class where I create a mock Order (on creation of which I expect a file to be created) , Content Version record never gets inserted.

    // Create mocks
    fflib_ApexMocks mocks = new fflib_ApexMocks();
    fflib_ISObjectUnitOfWork uowMock = new fflib_SObjectMocks.SObjectUnitOfWork(mocks);

    Id newId = fflib_IDGenerator.generate(Order.SObjectType);
    Application.unitOfWork.setMock(uowMock);

    // When
    ABC_OrdService service = (ABC_OrdService) new ABC_OrdService();
    service.storeFileOnOrder(new Set<Id>{ newId });

    // Then
    fflib_ArgumentCaptor argument = fflib_ArgumentCaptor.forClass(fflib_ISObjectUnitOfWork.class);
    //this always fails
    ((fflib_ISObjectUnitOfWork) mocks.verify(uowMock, 1)).registerNew((ContentVersion) v 
    argument.capture());

I did some debug and found that the set to which I'm adding content version id's after commit work is empty which is very strange.

system.debug(cVerIdSet); //this prints empty

Please note that when this runs as how it should be in practice (normal business process) I do get content version id on the set, the problem is specific to test class.

Also, when I replace uow.commitWork() with a simple insert content version is inserted properly on running test class .

Can someone explain me as to what i'm doing incorrectly here?

1 Answer 1

1

Some answers ..

system.debug(cVerIdSet); //this prints empty

This is because your testmethod mocks the UnitOfWork so no actual DML occurs and the ContentVersion is never inserted (only registeredNew) and thus never gets an ID

You should not need to use ArgumentCaptors here as there is a built-in matcher that verifies Sobjects. ArgumentCaptors are useful when you want to verify, say, the emailMessage object in registerEmail because there's no equals method to compare it against a mocked emailMessage.

I find it easier to registerNew object-by-object so I can use the sObjectWith matcher for a single SObject than using the sObjectsWith matcher for lists so, I'd rewrite your production code as:

for(Id recordId :recordIds) {
  // Add content version record
  ContentVersion cVerFile = new ContentVersion();
  cVerFile.VersionData = Blob.valueOf('Test'); 
  cVerFile.Title = 'File TEST';
  cVerFile.ContentLocation= 'S';
  cVerFile.PathOnClient = 'Test Name' + '.' + 'pdf';
  uow.registerNew(cVerFile);
}
uow.commitWork();

Now, you verify this as follows:

((fflib_SObjectUnitOfWork)mocks.verify(mockUow,mocks.times(1).description('sb ContentVersion created matching values')))
            .registerNew(fflib_Match.sObjectWith(new Map<SObjectField,Object> {
            ContentVersion.VersionData => Blob.valueOf('Test'),
            ContentVersion.Title => 'File TEST',
            ...}));

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .