Using this structure.
public class User
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public virtual bool IsAdministrator()
{
return false;
}
}
Is it possible to combine AutoFixture
and Moq
to accomplish the following?
User.FirstName
is auto-generatedUser.LastName
is always "Smith" (literal)User.MiddleName
is not populated (default)True
IsAdministrator()
was called.I know this seems so simple. Here's what I tried using AutoMoq
.
var config = new AutoMoqCustomization()
{
ConfigureMembers = true
};
var fixture = new AutoFixture.Fixture();
fixture.Customize(config);
fixture.Freeze<Mock<User>>()
.Setup(x => x.IsAdministrator())
.Returns(true);
var model = fixture.Build<User>()
.With(x => x.LastName, "Smith")
.Without(x => x.MiddleName)
.Create();
But that is clearly wrong. :( I am sure the syntax is simple. Thank you for any help.
My goal
: create an object with BOTH filled properties and mocked methods.
The following achieves the requested goals
public void AutoFixture_Should_Fill_Poperties_And_Mock_Methods() {
//Arrange
AutoMoqCustomization config = new AutoMoqCustomization() {
ConfigureMembers = true
};
IFixture fixture = new AutoFixture.Fixture().Customize(config);
Mock<User> mock = new Mock<User>();
mock
.Setup(x => x.IsAdministrator())
.Returns(true);
User model = fixture.Build<User>()
.FromSeed(s => mock.Object) //<--
.With(x => x.LastName, "Smith")
.Without(x => x.MiddleName)
.Create();
//Assert
//Ensure User.FirstName is auto-generated
model.FirstName.Should().NotBeNullOrEmpty();
//Ensure User.LastName is always "Smith" (literal)
model.LastName.Should().Be("Smith");
//Ensure User.MiddleName is not populated (default)
model.MiddleName.Should().BeNull();
//Ensure User.IsAdministrator() returns True
model.IsAdministrator().Should().BeTrue();
//Verify IsAdministrator() was called.
mock.Verify(_ => _.IsAdministrator());
}
An observation was that when using
Mock<User> mock = fixture.Freeze<Mock<User>>();
if would still populate the MiddleName
property even though it was explicitly told Without
for the build, but worked as desired when using
Mock<User> mock = new Mock<User>();
But if you were to explicitly set the member to return null
Mock<User> mock = fixture.Freeze<Mock<User>>(); // new Mock<User>();
mock
.Setup(x => x.IsAdministrator())
.Returns(true);
User model = fixture.Build<User>()
.FromSeed(s => mock.Object)
.With(x => x.LastName, "Smith")
.With(x => x.MiddleName, (string)null) //<--
.Create();
It worked.
Here is another variation of the test with a subject class that depends on the model to be injected.
[Test]
public void AutoFixture_Should_Fill_Poperties_And_Mock_Methods() {
//Arrange
AutoMoqCustomization config = new AutoMoqCustomization() {
ConfigureMembers = true
};
IFixture fixture = new AutoFixture.Fixture().Customize(config);
Mock<User> mock = new Mock<User>();
mock
.Setup(x => x.IsAdministrator())
.Returns(true);
User model = fixture.Freeze<User>(c => c
.FromSeed(s => mock.Object)
.With(x => x.LastName, "Smith")
.With(x => x.MiddleName, (string)null)
);
//Act
Subject subject = fixture.Create<Subject>();
bool actual = subject.Act();
//Assert
//Ensure User.FirstName is auto-generated
model.FirstName.Should().NotBeNullOrEmpty();
//Ensure User.LastName is always "Smith" (literal)
model.LastName.Should().Be("Smith");
//Ensure User.MiddleName is not populated (default)
model.MiddleName.Should().BeNull();
//Ensure User.IsAdministrator() returns True
actual.Should().BeTrue();
//model.IsAdministrator().Should().BeTrue();
//Verify IsAdministrator() was called.
mock.Verify(_ => _.IsAdministrator());
}
public class Subject {
private User model;
public Subject(User model) {
this.model = model;
}
public bool Act() => model.IsAdministrator();
}