AutoFixture will not work with register and additional customize call. If I do only one of the two, it works. The whole behavior of customize feature is hard to understand for me. Is this works as designed?
Goal: Use the greediest constructor AND OmitAutoProperties for special class.
public interface IDataProvider { }
public class FileDataProvider : IDataProvider {}
public class TestClass
{
public TestClass() : this (new FileDataProvider()) { }
public TestClass(IDataProvider dataProvider) { } // should be used from AutoFixture
}
[Fact]
public void Method_State_Result()
{
var fixture = new Fixture();
fixture.Register(() => fixture.Build<TestClass>().OmitAutoProperties().Create());
var dc1 = fixture.Create<TestClass>(); // working
fixture.Customize(new AutoNSubstituteCustomization());
fixture.Customizations.Add(new MethodInvoker(new GreedyConstructorQuery()));
var dc2 = fixture.Create<TestClass>(); // crash with "AutoFixture was unable to create an instance from System.SByte*, most likely because it has no public constructor, is an abstract or non-public type"
var dc3 = fixture.Create<TestClass>();
}
A workaround would be to do the registration like this. But feels not like the right solution...
fixture.Register(() => new Fixture().Build<TestClass>().OmitAutoProperties().Create());
If I understood the question correctly, then the easiest option is to provide a custom factory that uses a specimen builder.
fixture.Customize<TestClass>(c => c
.FromFactory(new MethodInvoker(new GreedyConstructorQuery()))
.OmitAutoProperties());
Here is a sample test.
public class TestClass
{
public TestClass() : this(new FileDataProvider())
{
}
public TestClass(IDataProvider dataProvider)
{
DataProvider = dataProvider;
}
public string SomeString { get; set; }
public IDataProvider DataProvider { get; }
}
[Fact]
public void FooTest()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
fixture.Customize<TestClass>(c => c
.FromFactory(new MethodInvoker(new GreedyConstructorQuery()))
.OmitAutoProperties());
var mockProvider = fixture.Freeze<IDataProvider>();
var testObject = fixture.Create<TestClass>();
Assert.Null(testObject.SomeString);
Assert.Same(mockProvider, testObject.DataProvider);
}
Related
I'm using AutoFixture to create a service which has a repository dependency injected through the constructor. When using fixture.Create<>, a mock repository is automatically provided for the dependency. I'd like to use CallBase on the mock repository so that it calls the method on the actual underlying class. Is this possible? The methods are defined as virtual so that Moq can override them. Below is a basic example and a test with AutoFixture which fails. Then the same test is shown using Moq directly which succeeds. The testing library being used is xUnit. Assume the interfaces have the shown methods defined.
Service:
public class PersonService : IPersonService {
private readonly IPersonRepository _personRepository;
public PersonService(IPersonRepository personRepository) {
_personRepository = personRepository;
}
public virtual string GetPersonName(int id) => _personRepository.GetPersonName(id);
}
Repository:
public class PersonRepository : IPersonRepository {
public virtual string GetPersonName(int id) => Data.People[id].FirstName!;
}
Data:
public static class Data {
public static List<Person> People { get; } = new() {
new Person { FirstName = "Jack" },
new Person { FirstName = "Jill" }
};
}
Person:
public class Person {
public string? FirstName { get; set; }
}
Failing Test with AutoFixture: result is null, the GetPersonName method on the repo is never called via CallBase
[Fact]
public void AutoFixture_Test_CallBase() {
var fixture = new Fixture();
fixture.Customize(new AutoMoqCustomization());
var mockPersonRepository = fixture.Freeze<Mock<PersonRepository>>();
mockPersonRepository.Setup(r => r.GetPersonName(It.IsAny<int>())).CallBase();
var sut = fixture.Create<PersonService>();
var result = sut.GetPersonName(1);
Assert.Equal(Data.People[1].FirstName, result);
}
The same test works fine using Moq without AutoFixture:
[Fact]
public void Moq_Test_CallBase() {
var mockPersonRepository = new Mock<PersonRepository>();
mockPersonRepository.Setup(r => r.GetPersonName(It.IsAny<int>())).CallBase();
var sut = new PersonService(mockPersonRepository.Object);
var result = sut.GetPersonName(1);
Assert.Equal(Data.People[1].FirstName, result);
}
The problem is that when PersonService is created by AutoFixture, it uses the Mock<IPersonRepository> to build up an IPersonRepository but in your code it is not defined so it uses the default.
Since you want to setup the Mock<IPersonRepository> with CallBase, one approach would be to freeze a Mock<PersonRepository> and then, whenever an IPersonRepository is required by AutoFixture to build up any other object that depends on it (like the PersonService) you call fixture.Create<PersonRepository>()
So it'd be like this:
[Fact]
public void AutoFixture_Test_CallBase()
{
var fixture = new Fixture();
fixture.Customize(new AutoMoqCustomization());
var mockPersonRepository = fixture.Freeze<Mock<PersonRepository>>();
mockPersonRepository
.Setup(r => r.GetPersonName(It.IsAny<int>()))
.CallBase();
fixture.Register<IPersonRepository>(() => fixture.Create<PersonRepository>());
var sut = fixture.Create<PersonService>();
var result = sut.GetPersonName(1);
Assert.Equal(Data.People[1].FirstName, result);
}
I have a below class, which having base class and I am trying to write unit test.
public class CarService : ServiceBase, IProvisioningService
{
private IAuditRepository _repository;
public CarService(IHostingFactory hostingFactory) : base(name, hostingFactory)
{
}
public override void DoWork()
{
if (_repository == null)
{
//its calling the base method.
_repository = CurrentContext.ContainerFactory.GetInstance<IAuditRepository>();
try
{
_repository.Insert("something");
}
catch (Exception ex)
{
}
}
}
}
CurrentContext.ContainerFactory is part of base class. CurrentContext.ContainerFactory throws null exception. How do I create Mock for these classes?
Is interface is must for unit testing?
Updated with base class
public abstract class ServiceBase : IServiceBase
{
public HostingContext CurrentContext { get; }
public string ServiceName { get; }
protected ServiceBase(string serviceName, IHostingFactory hostingFactory)
{
ServiceName = serviceName;
_stopSignal = false;
CurrentContext = hostingFactory.CreateContext(serviceName);
Logger = CurrentContext.LoggerInstance;
}
}
HostingContext class
public class HostingContext
{
public HostingContext(
Func<string, ILogger> loggerFactory,
string serviceName,
string connString): this(loggerFactory(contextName),serviceName, connString, new ContainerFactory())
{}
}
Unit Test Class
MockRepository repository = new MockRepository(MockBehavior.Default);
var containerFactoryMock = repository.Create<IContainerFactory>();
var auditRepositoryMock = repository.Create<IAuditRepository>();
var hostingFactoryMock = repository.Create<IHostingFactory>();
var hostingContextMock = new HostingContext("Sample", "ConnString",containerFactoryMock.Object);
hostingFactoryMock.Setup(factory => factory.CurrentContext(It.IsAny<string>()))
.Returns(hostingContextMock);
CarService carService = new CarService(hostingFactoryMock.Object);
carService.Work();
You did not setup the container factory's behavior so when you call .GetInstance<IAuditRepository>() it will return null, hence your error.
Provide the class under test with the necessary dependencies to allow the test to be exercised to completion.
//Arrange
var repository = new MockRepository(MockBehavior.Default);
var containerFactoryMock = repository.Create<IContainerFactory>();
var auditRepositoryMock = repository.Create<IAuditRepository>();
var hostingFactoryMock = repository.Create<IHostingFactory>();
var loggerMock = repository.Create<ILogger>();
var hostingContextMock = new HostingContext(loggerMock, "Sample", "ConnString",containerFactoryMock.Object);
hostingFactoryMock
.Setup(_ => _.CreateContext(It.IsAny<string>()))
.Returns(hostingContextMock);
containerFactoryMock
.Setup(_ => _.GetInstance<IAuditRepository>())
.Returns(auditRepositoryMock);
CarService carService = new CarService(hostingFactoryMock.Object);
//Act
carService.Work();
//Assert
auditRepositoryMock.Verify(_ => _.Insert(It.IsAny<string>()), Times.Once);
I've got a setup like this with a concrete class that is instantiated inside the method I want to test. I want to mock this concrete class an not have it execute the code inside. Hence, no exception should be thrown:
public class Executor
{
public bool ExecuteAction(ActionRequest request)
{
switch (request.ActionType)
{
case ActionType.Foo:
var a = new Foo();
return a.Execute(request);
case ActionType.Bar:
var b = new Bar();
return b.Execute(request);
}
return true;
}
}
public class Foo
{
public virtual bool Execute(ActionRequest request)
{
throw new NotImplementedException();
}
}
public class Bar
{
public virtual bool Execute(ActionRequest request)
{
throw new NotImplementedException();
}
}
My NUnit test looks like this:
[Test]
public void GivenARequestToFooShouldExecuteFoo()
{
var action = new Mock<Foo>();
action.Setup(x => x.Execute(It.IsAny<ActionRequest>())).Returns(true);
var sut = new Mock<Executor>();
sut.Object.ExecuteAction(new ActionRequest
{
ActionType = ActionType.Foo
});
}
[Test]
public void GivenARequestToBarShouldExecuteBar()
{
var action = new Mock<Bar>();
action.Setup(x => x.Execute(It.IsAny<ActionRequest>())).Returns(true);
var sut = new Mock<Executor>();
sut.Object.ExecuteAction(new ActionRequest
{
ActionType = ActionType.Bar
});
}
I fiddled around with CallBase, but it didn't get me anywhere. Is there anyway I can solve this easily without dependency injection of these classes and adding interfaces? Is this possible just using Moq?
The only thing I can think to do currently is move the Execute methods into the Executor class and rename them to ExecuteFoo() and ExecuteBar(), but I have a lot of code to move so they'd have to be partial classes (sub classes?).
The problem is not with the mocking of the method but with the creation of the concrete class. The creation of Foo and Bar need to be inverted out of the Executor. It is responsible for executing the action, not creating it. with that this interface was created to handle the creation.
public interface IActionCollection : IDictionary<ActionType, Func<IExecute>> {
}
think of this as a collection of factories or a collection of creation strategies.
A common interface was created for the actions.
public interface IExecute {
bool Execute(ActionRequest request);
}
public class Foo : IExecute {
public virtual bool Execute(ActionRequest request) {
throw new NotImplementedException();
}
}
public class Bar : IExecute {
public virtual bool Execute(ActionRequest request) {
throw new NotImplementedException();
}
}
And the Executor was refactored to use dependency inversion.
public class Executor {
readonly IActionCollection factories;
public Executor(IActionCollection factories) {
this.factories = factories;
}
public bool ExecuteAction(ActionRequest request) {
if (factories.ContainsKey(request.ActionType)) {
var action = factories[request.ActionType]();
return action.Execute(request);
}
return false;
}
}
With that refactor done the Executor can be tested with fake actions.
public void GivenARequestToFooShouldExecuteFoo() {
//Arrange
var expected = true;
var key = ActionType.Foo;
var action = new Mock<Foo>();
action.Setup(x => x.Execute(It.IsAny<ActionRequest>())).Returns(expected);
var actions = new Mock<IActionCollection>();
actions.Setup(_ => _[key]).Returns(() => { return () => action.Object; });
actions.Setup(_ => _.ContainsKey(key)).Returns(true);
var sut = new Executor(actions.Object);
var request = new ActionRequest {
ActionType = ActionType.Foo
};
//Act
var actual = sut.ExecuteAction(request);
//Assert
Assert.AreEqual(expected, actual);
}
A production implementation of the factory collection can look like this
public class ActionCollection : Dictionary<ActionType, Func<IExecute>>, IActionCollection {
public ActionCollection()
: base() {
}
}
and configured accordingly with your concrete types.
var factories = ActionCollection();
factories[ActionType.Foo] = () => new Foo();
factories[ActionType.Bar] = () => new Bar();
I have a service class, it creates a new concrete PropertyClass, before doing action. I'm trying to test if DoSomething() was run.
Is it possible to create stud and control the returned Property value to a mock object?
public class ServiceClass
{
public PropertyClass Property {set; get;}
public void Action()
{
Property = new PropertyClass();
Property.DoSomething();
}
}
[Test] // This test does not work.
public class Action_Test
{
var service = new ServiceClass();
var mockPropertyClass = MockRepository.GenerateMock<IPropertyClass>();
service.Property.Stub(x=> new PropertyClass()).Return(mockPropertyClass);
service.Action();
service.Property.AssertWasCalled(x => x.DoSomething());
}
No. But you could easily mitigate this problem with factory design pattern. Consider:
public class ServiceClass
{
private readonly IPropertyClassFactory factory;
public PropertyClass Property { get; private set; }
public ServiceClass(IPropertyClassFactory factory)
{
this.factory = factory;
}
public void Action()
{
Property = factory.CreateInstance();
Property.DoSomething();
}
}
In test you create mocked factory which returns mocked object. Like this:
[Test]
public class Action_Test
{
var factoryMock = MockRepository.GenerateMock<IPropertyClassFactory>();
var propertyMock = MockRepository.GenerateMock<IPropertyClass>();
factoryMock.Stub(f => f.CreateInstance()).Returns(propertyMock);
var service = new ServiceClass(factoryMock);
service.Action();
propertyMock.AssertWasCalled(x => x.DoSomething());
}
Note that when factory is this simple, you might just as well use Func<IPropertyClass> instead of creating extra class/interface pair.
Your Action method is creating its own instance of PropertyClass which is overwriting your stub.
public void Action()
{
if (Property == null)
Property = new PropertyClass();
Property.DoSomething();
}
A nice way around having to check each time you use Property property, would be to assign the property in the constructor.
public ServiceClass() {
Property = new PropertyClass();
}
Then the Action method would just be:
public void Action()
{
Property.DoSomething();
}
I encountered a class during my work that looks like this:
public class MyObject
{
public int? A {get; set;}
public int? B {get; set;}
public int? C {get; set;}
public virtual int? GetSomeValue()
{
//simplified behavior:
return A ?? B ?? C;
}
}
The issue is that I have some code that accesses A, B and C and calls the GetSomeValue() method (now, I'd say this is not a good design, but sometimes my hands are tied ;-)). I want to create a mock of this object, which, at the same time, has A, B and C set to some values. So, when I use moq as such:
var m = new Mock<MyObject>() { DefaultValue = DefaultValue.Mock };
lets me setup a result on GetSomeValue() method, but all the properties are set to null (and setting up all of them using Setup() is quite cumbersome, since the real object is a nasty data object and has more properties than in above simplified example).
So on the other hand, using AutoFixture like this:
var fixture = new Fixture();
var anyMyObject = fixture.CreateAnonymous<MyObject>();
Leaves me without the ability to stup a call to GetSomeValue() method.
Is there any way to combine the two, to have anonymous values and the ability to setup call results?
Edit
Based on nemesv's answer, I derived the following utility method (hope I got it right):
public static Mock<T> AnonymousMock<T>() where T : class
{
var mock = new Mock<T>();
fixture.Customize<T>(c => c.FromFactory(() => mock.Object));
fixture.CreateAnonymous<T>();
fixture.Customizations.RemoveAt(0);
return mock;
}
This is actually possible to do with AutoFixture, but it does require a bit of tweaking. The extensibility points are all there, but I admit that in this case, the solution isn't particularly discoverable.
It becomes even harder if you want it to work with nested/complex types.
Given the MyObject class above, as well as this MyParent class:
public class MyParent
{
public MyObject Object { get; set; }
public string Text { get; set; }
}
these unit tests all pass:
public class Scenario
{
[Fact]
public void CreateMyObject()
{
var fixture = new Fixture().Customize(new MockHybridCustomization());
var actual = fixture.CreateAnonymous<MyObject>();
Assert.NotNull(actual.A);
Assert.NotNull(actual.B);
Assert.NotNull(actual.C);
}
[Fact]
public void MyObjectIsMock()
{
var fixture = new Fixture().Customize(new MockHybridCustomization());
var actual = fixture.CreateAnonymous<MyObject>();
Assert.NotNull(Mock.Get(actual));
}
[Fact]
public void CreateMyParent()
{
var fixture = new Fixture().Customize(new MockHybridCustomization());
var actual = fixture.CreateAnonymous<MyParent>();
Assert.NotNull(actual.Object);
Assert.NotNull(actual.Text);
Assert.NotNull(Mock.Get(actual.Object));
}
[Fact]
public void MyParentIsMock()
{
var fixture = new Fixture().Customize(new MockHybridCustomization());
var actual = fixture.CreateAnonymous<MyParent>();
Assert.NotNull(Mock.Get(actual));
}
}
What's in MockHybridCustomization? This:
public class MockHybridCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(
new MockPostprocessor(
new MethodInvoker(
new MockConstructorQuery())));
fixture.Customizations.Add(
new Postprocessor(
new MockRelay(t =>
t == typeof(MyObject) || t == typeof(MyParent)),
new AutoExceptMoqPropertiesCommand().Execute,
new AnyTypeSpecification()));
}
}
The MockPostprocessor, MockConstructorQuery and MockRelay classes are defined in the AutoMoq extension to AutoFixture, so you'll need to add a reference to this library. However, note that it's not required to add the AutoMoqCustomization.
The AutoExceptMoqPropertiesCommand class is also custom-built for the occasion:
public class AutoExceptMoqPropertiesCommand : AutoPropertiesCommand<object>
{
public AutoExceptMoqPropertiesCommand()
: base(new NoInterceptorsSpecification())
{
}
protected override Type GetSpecimenType(object specimen)
{
return specimen.GetType();
}
private class NoInterceptorsSpecification : IRequestSpecification
{
public bool IsSatisfiedBy(object request)
{
var fi = request as FieldInfo;
if (fi != null)
{
if (fi.Name == "__interceptors")
return false;
}
return true;
}
}
}
This solution provides a general solution to the question. However, it hasn't been extensively tested, so I'd love to get feedback on it.
Probably there is a better why, but this works:
var fixture = new Fixture();
var moq = new Mock<MyObject>() { DefaultValue = DefaultValue.Mock };
moq.Setup(m => m.GetSomeValue()).Returns(3);
fixture.Customize<MyObject>(c => c.FromFactory(() => moq.Object));
var anyMyObject = fixture.CreateAnonymous<MyObject>();
Assert.AreEqual(3, anyMyObject.GetSomeValue());
Assert.IsNotNull(anyMyObject.A);
//...
Initially I tried to use fixture.Register(() => moq.Object); instead of fixture.Customize but it registers the creator function with OmitAutoProperties() so it wouldn't work for you case.
As of 3.20.0, you can use AutoConfiguredMoqCustomization. This will automatically configure all mocks so that their members' return values are generated by AutoFixture.
var fixture = new Fixture().Customize(new AutoConfiguredMoqCustomization());
var mock = fixture.Create<Mock<MyObject>>();
Assert.NotNull(mock.Object.A);
Assert.NotNull(mock.Object.B);
Assert.NotNull(mock.Object.C);