locked
Unit Test setting FontAttributes throws You Must Call Init() exception RRS feed

  • Question

  • User383863 posted

    I have an application where I need to have text with multiple attributes displayed in the same label or text field, and the proper answer appears to be to use the FormattedString class and add a new Span to it for each change I need to make. The changes I need to support include text color, bold, and underline. Since I want to be able to test my conversions, I created a class to do the conversions separately from the UI. This class looks at the definitions of the text segments and applies the TextDecoration for underline, the TextColor, or the FontAttribute for bold as necessary. All was fine with TextDecoration and TextColor, however when I tried the following code: if (itemSegment.IsBold) { segmentSpan.FontAttributes = FontAttributes.Bold; } my unit tests throw an exception "System.InvalidOperationException: You MUST call Xamarin.Forms.Init(); prior to using it."

    I can only assume from research that the FontAttributes is calling something like the DependencyService or DeviceInfo in the background.

    Is anyone aware of a way I can mock the initialization in an MS test so that I can unit test this code?

    TIA Ron L.

    Wednesday, May 1, 2019 4:51 PM

Answers

  • User89714 posted

    @rlounsbury

    Your Models and ViewModels should hopefully not have any dependencies on Xamarin.Forms, so you should be able to unit test those with fakes/mocks as required easily enough.

    Unit testing your View (which is where any Xamarin.Forms-dependent code should be) is not something many people do. Most will system/integration test the app using UITest or similar, so that the View is tested in combination with the ViewModels and Models.

    However, if you do need to unit test code that is dependent upon Xamarin.Forms, take a look at how Xamarin do it. For example, if you look at FormattedStringTests.cs in the Xamarin.Forms repository, you will see:

    Device.PlatformServices = new MockPlatformServices ();

    Device.PlatformServices is internal, and has the attribute [EditorBrowsable(EditorBrowsableState.Never)], but that doesn't mean that you cannot make use of it, if you are willing to take the risk that it might not be present in a future release of XF.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Thursday, May 2, 2019 9:25 AM

All replies

  • User89714 posted

    @rlounsbury

    Your Models and ViewModels should hopefully not have any dependencies on Xamarin.Forms, so you should be able to unit test those with fakes/mocks as required easily enough.

    Unit testing your View (which is where any Xamarin.Forms-dependent code should be) is not something many people do. Most will system/integration test the app using UITest or similar, so that the View is tested in combination with the ViewModels and Models.

    However, if you do need to unit test code that is dependent upon Xamarin.Forms, take a look at how Xamarin do it. For example, if you look at FormattedStringTests.cs in the Xamarin.Forms repository, you will see:

    Device.PlatformServices = new MockPlatformServices ();

    Device.PlatformServices is internal, and has the attribute [EditorBrowsable(EditorBrowsableState.Never)], but that doesn't mean that you cannot make use of it, if you are willing to take the risk that it might not be present in a future release of XF.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Thursday, May 2, 2019 9:25 AM
  • User383863 posted

    JohnHardman Thank you for your response. That was what I needed.
    I added the MockPlatformServices.cs file which was in the same repository to my test project, and added the following lines in my test: [TestInitialize] public void TestInitialization() { Device.PlatformServices = new MockPlatformServices(); }

    Also, just to clarify, my use case is that my business rules require that certain information be highlighted to the user using bold and/or text color. I had created view-independent classes for storing the text and required formatting but needed to have a converter to convert from the independent classes to the Xamarin FormattedText instance. I believe that the converter rightly belongs in the ViewModel layer since it is managing a model to view matching. It was this converter that I was trying to unit test.

    Thursday, May 2, 2019 12:59 PM
  • User89714 posted

    @rlounsbury said: Thank you for your response. That was what I needed.

    Glad to have helped.

    I believe that the converter rightly belongs in the ViewModel layer since it is managing a model to view matching. It was this converter that I was trying to unit test.

    The only converters (three of them) that I have in the ViewModel are ones knocked together whilst experimenting, but that are due to be re-factored and moved to the View layer. The vast majority (> 40 and still increasing) are already in the View layer. Whilst converters can appear anywhere, I would work on the basis that any converter involving a Xamarin.Forms type ideally wants to be in the View layer. The test for the purist is could you replace your View layer so that Xamarin.Forms is replaced by some theoretical other UI framework, without having to change the Model or ViewModel?

    Thursday, May 2, 2019 1:44 PM
  • User383863 posted

    JonHardman

    I see your point. I will have to take a look at doing that refactor then. Thank you for your time.

    Thursday, May 2, 2019 1:51 PM