Skip to content

Commit

Permalink
Merge pull request #1241 from stakx/setup-property-recursive
Browse files Browse the repository at this point in the history
Make `SetupProperty` work with recursive expressions again
  • Loading branch information
stakx committed Mar 6, 2022
2 parents dcf631e + e4c46d7 commit 83a9874
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 16 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
The format is loosely based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).


## Unreleased

#### Fixed

* Regression: Property stubs not working on sub mock (@aaronburro, #1240)


## 4.17.1 (2022-02-26)

#### Added
Expand Down
24 changes: 24 additions & 0 deletions src/Moq/Mock.cs
Expand Up @@ -609,6 +609,30 @@ internal static SequenceSetup SetupSequence(Mock mock, LambdaExpression expressi
});
}

internal static StubbedPropertySetup SetupProperty(Mock mock, LambdaExpression expression, object initialValue)
{
Guard.NotNull(expression, nameof(expression));

var pi = expression.ToPropertyInfo();

if (!pi.CanRead(out var getter))
{
Guard.CanRead(pi);
}

if (!pi.CanWrite(out var setter))
{
Guard.CanWrite(pi);
}

return Mock.SetupRecursive(mock, expression, (targetMock, _, _) =>
{
var setup = new StubbedPropertySetup(targetMock, expression, getter, setter, initialValue);
targetMock.MutableSetups.Add(setup);
return setup;
});
}

private static TSetup SetupRecursive<TSetup>(Mock mock, LambdaExpression expression, Func<Mock, Expression, MethodExpectation, TSetup> setupLast, bool allowNonOverridableLastProperty = false)
where TSetup : ISetup
{
Expand Down
17 changes: 1 addition & 16 deletions src/Moq/Mock`1.cs
Expand Up @@ -628,22 +628,7 @@ public Mock<T> SetupProperty<TProperty>(Expression<Func<T, TProperty>> property)
/// </example>
public Mock<T> SetupProperty<TProperty>(Expression<Func<T, TProperty>> property, TProperty initialValue)
{
Guard.NotNull(property, nameof(property));

var pi = property.ToPropertyInfo();

if (!pi.CanRead(out var getter))
{
Guard.CanRead(pi);
}

if (!pi.CanWrite(out var setter))
{
Guard.CanWrite(pi);
}

var setup = new StubbedPropertySetup(this, property, getter, setter, initialValue);
this.MutableSetups.Add(setup);
Mock.SetupProperty(this, property, initialValue);
return this;
}

Expand Down
42 changes: 42 additions & 0 deletions tests/Moq.Tests/Regressions/IssueReportsFixture.cs
Expand Up @@ -3740,6 +3740,48 @@ public void Pass_byte_array_indirectly_via_method_call()

#endregion

#region 1240

public class Issue1240
{
public interface IFoo { IBar Bar { get; } }
public interface IBar
{
string Prop1 { get; }
string Prop2 { get; set; }
}

[Fact]
public void Property_on_submock_should_be_stubbed_1()
{
const string prop2 = "Prop2";
var mock = new Mock<IFoo>();

// mock.SetupGet(m => m.Bar.Prop1).Returns("Prop1");
// ^ This line being commented out is the only difference from the test below.
// Its absence would cause a `NullReferenceException` later.

mock.SetupProperty(m => m.Bar.Prop2);
mock.Object.Bar.Prop2 = prop2;
Assert.Equal(prop2, mock.Object.Bar.Prop2);
}

[Fact]
public void Property_on_submock_should_be_stubbed_2()
{
const string prop2 = "Prop2";
var mock = new Mock<IFoo>();

mock.SetupGet(m => m.Bar.Prop1).Returns("Prop1");

mock.SetupProperty(m => m.Bar.Prop2);
mock.Object.Bar.Prop2 = prop2;
Assert.Equal(prop2, mock.Object.Bar.Prop2);
}
}

#endregion

// Old @ Google Code

#region #47
Expand Down

0 comments on commit 83a9874

Please sign in to comment.