1

I'm using FluentAssertions to check the view models. I would like to verify correctly raising PropertyChanged events for the properties.

This is working fine when signaling individual properties:

public string MyName {
  get => this.myName;
  set => {
    this.myName = value;
    this.FirePropertyChanged(nameof(this.MyName));
  }
}
...
sut.MonitorEvents();
sut.ShouldRaisePropertyChangeFor(model => model.MyName); // OK

Some complex view models wants to refresh all properties and raised null or string.Empty which causes the view to refresh (MSDN). But the FluentAssertions call does not accept this as valid change.

public string IsServer {
  get => this.isServer;
  set => {
    this.isServer = value;
    this.FirePropertyChanged(string.Empty);
  }
}
...
sut.MonitorEvents();
sut.ShouldRaisePropertyChangeFor(model => model.IsServer); // FAILED

Is there an option to check the events like this?

Nkosi
  • 235,767
  • 35
  • 427
  • 472
lg2de
  • 616
  • 4
  • 16

2 Answers2

1

ShouldRaisePropertyChangeFor expects an expression which, while works for null does not work for empty string. It is still possible to use the ShouldRaise to check if the PropertyChanged event was raised with a specific PropertyChangedEventArgs.

Given

public string IsServer {
  get => this.isServer;
  set => {
    this.isServer = value;
    this.FirePropertyChanged(string.Empty);
  }
}

With the following test

//Arrange
var sut = new Sut();

sut.MonitorEvents();

//Act
sut.IsServer = "Hello World";

//Assert
sut.ShouldRaise("PropertyChanged")
    .WithArgs<PropertyChangedEventArgs>(e => e.PropertyName == string.Empty);

ShouldRaise(...).WithArgs<>(...) should satisfy the requirements of the test

The above could be encapsulated into is own extension method building upon the original idea.

public static class AllPropertiesChangedSourceExtensions {
    private const string PropertyChangedEventName = "PropertyChanged";
    public static FluentAssertions.Events.IEventRecorder ShouldRaisePropertyChangeFor<T>(this T eventSource, string propertyName) {
        return eventSource.ShouldRaise(PropertyChangedEventName)
            .WithSender(eventSource)
            .WithArgs<PropertyChangedEventArgs>(args => args.PropertyName == propertyName);
    }
}

And called

//Assert
sut.ShouldRaisePropertyChangeFor(string.Empty); //Or null depending on which was used

As an aside, when called with string.Empty or null the event does not actually call all the properties as raised. The framework listening to the event which gets those values will notify the UI based on the fact that null or empty string was raised as property name.

Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • Thanks for your response, but it does not really answer my question. Maybe it was not fully described. From users point of view I want to verify raise of individual "PropertyChanged" even the implementation raises with `string.empty`. The kind of PropertyChanged is not relevant for the view, so it should be relevant for the test. – lg2de May 31 '17 at 07:29
0

You should (no pun intended) be able to call sut.ShouldRaisePropertyChangeFor(null).

Dennis Doomen
  • 8,368
  • 1
  • 32
  • 44
  • `null` works but not for `string.Empty`. Created an additional extension for that edge case. – Nkosi May 29 '17 at 18:29