2

I am in the process of setting up some unit tests for a Sitecore project (using this guide as a starting point: https://www.codeflood.net/blog/2020/05/17/logicless-view-itemless-model/)

I have come across a problem when trying to mock call MediaManager.GetMediaUrl(MediaItem).

This is the method I would like to test:

public string GetImageUrl(Item item, string fieldName, MediaUrlBuilderOptions options = null)
{
  if (item == null)
    return String.Empty;

  if(string.IsNullOrWhiteSpace(fieldName))
    return String.Empty;

  var imgField = (ImageField)item.Fields[fieldName];

  if (imgField != null && imgField.MediaItem != null)
  {
    return (options != null) ?
      HashingUtils.ProtectAssetUrl(MediaManager.GetMediaUrl(imgField.MediaItem, options)) :
      HashingUtils.ProtectAssetUrl(MediaManager.GetMediaUrl(imgField.MediaItem));
  }

  return String.Empty;
}

I have tried updating the code to pass in BaseMediaManager through DI:

public ImageTaxonomy(BaseMediaManager mediaManager)
{
    Assert.ArgumentNotNull(mediaManager, "mediaManager");
    _mediaManager = mediaManager;
}
...
_mediaManager.GetMediaUrl(imgField.MediaItem)

And then used the following nSubstitute code in my unit test:

var mediaItem = CreateMediaItem(database);
var mediaManager = Substitute.For<BaseMediaManager>();

mediaManager.GetMediaUrl(mediaItem).Returns("/a/path/to/an/image.jpg");

var sut = new ImageTaxonomy(mediaManager);

...
private Item CreateMediaItem(Database database = null)
{
    var definition = new ItemDefinition(mediaItemID, "Mock Media Item", ID.Null, ID.Null);
    var data = new ItemData(definition, Language.Current, Sitecore.Data.Version.First, new FieldList());
    var mediaItem = new Item(mediaItemID, data, database);
    return mediaItem;
}

However the call to _mediaManager.GetMediaUrl(imgField.MediaItem) always returns an empty string.

I am guessing the reason is, I shouldnt be mocking the BaseMediaManager class, as it doesnt contain virtual members? Even though this Sitecore page indicates that it should be virtual (https://doc.sitecore.com/xp/en/developers/93/sitecore-experience-manager/build-item-and-media-urls.html).

If that is indeed the case, how would you normally approach creating unit tests for cases that call the GetMediaUrl() function? I would have thought this is quite a common scenario to test.

Note: this is a continuation on from this previous question (which has more info on unit test being carried out): How to mock an ImageField in Sitecore using nSubstitute and xUnit

1 Answer 1

1

Change

mediaManager.GetMediaUrl(mediaItem).Returns("/a/path/to/an/image.jpg");

to

mediaManager.GetMediaUrl(Arg.Is<MediaItem>(mi => mi.ID == mediaItem.ID)).Returns("/a/path/to/an/image.jpg");

Looks like there happens something with object references in the background so that's not the same object anymore and in result the equality comparer thinks it's a different object.

3
  • That's great thanks Marek. Could I ask what your recommendation regarding the static call to HashingUtils.ProtectAssetUrl()? I understand static calls should be avoided in unit tests? Would you move it into view or is there another alternative? As it stands it throwing an exception and failing the test. Commented Jan 12, 2022 at 14:10
  • 1
    You don't want to test HashingUtils. You can have 2 types, ServiceUnderTest and ServiceUnderTestWithMediaProtection. 2nd one having InnerServiceUnderTest and just calling HashingUtils on the result of inner one. You test the inner one only. It will give you flexibility to still use your code if you decide to skip media protection, just by changing your DI configuration. That's a quick thought and should be checked if not causing any issues.
    – Marek Musielak
    Commented Jan 12, 2022 at 14:44
  • Great I will try that approach out. Commented Jan 12, 2022 at 14:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.