How to add a specific implementation of a Mock created with Autofixture? - c#

I am writing tests for class (lets call it Sut) which has some dependencies injected via constructors. For this class I have to use the constructor with the most parameters, therefore I used the AutoMoqDataAttributeGreedy implementation:
public class AutoMoqDataAttribute : AutoDataAttribute
{
public AutoMoqDataAttribute() : base(new Fixture().Customize(new AutoMoqCustomization()))
{
}
}
public class AutoMoqDataAttributeGreedy : AutoDataAttribute
{
public AutoMoqDataAttributeGreedy() : base(new Fixture(new GreedyEngineParts()).Customize(new AutoMoqCustomization()))
{
}
}
The constructor of my sut looks like this:
public class Sut(IInerface1 interface1, IInterface2 interface2, IInterface3 interface3)
{
Interface1 = interface1;
Interface2 = interface2;
Interface3 = interface3;
}
One example test looks like this:
[Theory, AutoMoqDataAttributeGreedy]
public void SomeTest([Frozen]Mock<IInterface1> mock1 ,
Mock<IInterface2> mock2,
Sut sut,
SomOtherdata data)
{
// mock1 and mock2 Setup omitted
// I want to avoid following line
sut.AddSpeficicInterfaceImplementation(new IInterface3TestImplementation());
sut.MethodIWantToTest();
//Assert omitted
}
The problem is that I need a specific implementation of IInterface3 for testing and I want to avoid adding a method to my SUT (Interface3TestImplementation) only for my unit test and I also I want to avoid repeating code since I have to add this instance in each and every test.
Is there a nice and neat way to have this implementation being added for all my test / for specific tests with Autofixture?

If you need to do this as a one-off test, then the answer by Enrico Campidoglio is the way to go.
If you need this as a general rule throughout all of your unit tests, you can customize the Fixture with a TypeRelay:
fixture.Customizations.Add(
new TypeRelay(
typeof(IInterface3),
typeof(IInterface3TestImplementation));
This will change fixture so that, whenever IInterface3 is needed, an instance of IInterface3TestImplementation will be created and used.

Using your IFixture that you have created, you can call .Register against a specific interface and supply the object to use when that interface is then subsequently used.
e.g.
_fixture = new Fixture().Customize(new AutoMoqCustomization());
_fixture.Register<Interface3>(() => yourConcreteImplementation);
You could also use mocking that would allow you to then use .Freeze on the fixture and that way you could just set some expected calls against the interface and wouldn't need a completely concrete instance. You could let AutoFixture create a default implementation for you and apply the setup that you configured.
e.g.
var mockedInterface = _fixture.Freeze<Mock<Interface3>>();
mockedInterface
.Setup(x => x.PropertyOnInterface)
.Returns("some value");

You can have AutoFixture create an instance of a concrete type and tell it to use that instance every time it has to provide a value for any of its implemented interfaces. Here's an example:
[Theory, AutoMoqDataAttributeGreedy]
public void SomeTest(
[Frozen]Mock<IInterface1> mock1,
[Frozen]Mock<IInterface2> mock2,
[Frozen(Matching.ImplementedInterfaces)]IInterface3TestImplementation impl3,
Sut sut)
{
}
In this case, AutoFixture is going to create an instance of IInterface3TestImplementation and use it every time it encounters an interface implemented by that type.
This means that if the constructor of Sut has a parameter of type IInterface3, AutoFixture is going to pass it the the same instance that's being assigned to the impl3 parameter, which you can use in your test.
As an aside, there are other ways of matching frozen instances to types and members other than just by interface. If you want to know more, take a look at the members of the Matching enumeration.

Related

Customising constructor inputs to an abstract class in AutoFixture

While trying to unit test a service method, the base abstract class constructor that it implements contains 2 parameters. I want to customise these parameters while invoking the service using Auto-fixture.
The base service code is as below.
public abstract class ServiceBase : IHostedService, IDisposable
{
private readonly CronExpression _expression;
private readonly TimeZoneInfo _timeZoneInfo;
protected BaseService(string cronExpression, TimeZoneInfo timeZoneInfo)
{
_expression = CronExpression.Parse(cronExpression);
_timeZoneInfo = timeZoneInfo;
}
public abstract Task ExecuteTask(CancellationToken cancellationToken);
.
.
}
Another Service inherits from this base abstract class
public class TestService : ServiceBase
{
public override async Task ExecuteTask(CancellationToken stoppingToken)
{
//Implementation here
}
}
In my Unit test I'm invoking the ExecuteTask function as below
Func<Task> executeAction = async () => await sut.ExecuteTask(A<CancellationToken>._);
executeAction.Should().NotThrow();
AutoFixture tries to pass a random string to the CronExpression constructor parameter in BaseService class. Problem is this CronExpression has to be in a specific format or else an error occurs while trying to Parse it CronExpression.Parse(cronExpression)
How can i pass a custom value for constructor parameters?
Thanks in advance.
AutoFixture doesn't know about the domain constraints for the string parameter to your class. This should give a hint that, perhaps this type isn't the most appropriate parameter to the class. This is a classic example of Primitive Obsession.
You might enhance your service to, instead, directly accept the type that encapsulates the idea that this is a CronExpression:
protected ServiceBase(CronExpression cronExpression, TimeZoneInfo timeZoneInfo)
{
_cronExpression = cronExpression;
...
}
This way, it's guaranteed that the BaseService will be passed a valid CronExpression. If it wasn't, then creation of the CronExpression will have already failed.
You might think that we've simply shifted the problem: How do you now tell AutoFixture to create a valid CronExpression?
The advantage of shifting the work to building a CronExpression is that any customization made to create a valid CronExpression is now reusable for any other type that will require it. This will reduce ceremony for any future tests that will end up needing that type. Not to mention all the other benefits of avoiding primitive obsession.
Regarding telling AutoFixture how to create a valid CronExpression, there are many options. You might directly inject a single valid one:
fixture.Inject(CronExpression.Parse("myValidCronExpression"));
If you want to be able to select multiple, you could use ElementsBuilder to select from a pool of valid values:
public void Test()
{
var fixture = new Fixture();
fixture.Customizations.Add(new ElementsBuilder<CronExpression>(
new[] { "validExpr1", "validExpr2" }
.Select(s => CronExpression.Parse(s))
.ToArray()))
...
}
The most control of creation for that type would be afforded by creating an implementation of ISpecimenBuilder, which I'll omit in this answer. If you want to go that route, there are many examples both here and elsewhere.
After one of those customizations is made to AutoFixture, creation of your sut will work:
var sut = fixture.Create<TestService>();
Note: I haven't tested if TimeZoneInfo can directly be instantiated by AutoFixture's default specimen builders. If it can't, a similar method can be used for that type as well.

Mocking constructor dependencies using AutoMoq attribute

I'm wondering if there is a way of setting up a mock for a dependency before the constructor of the System Under Test (SUT) is called when using a test case that sets up AutoData.
My SUT looks like:
class Sut
{
private readonly IFoo foo;
public Sut(IFooFactory factory)
{
this.foo = factory.Build(1, 2);
}
public IFoo Foo
{
get
{
return this.foo;
}
}
}
So the test that I'm writing looks like:
[Theory]
[AutoData]
internal void Foo_IsCorrectlySet_Test(
[Frozen] Mock<IFooFactory> fooFactory,
IFoo foo,
Sut sut)
{
fooFactory.Setup(mock => mock.Build(1, 2))
.Returns(foo)
.Verifiable();
var actual = sut.Foo;
Assert.Equal(foo, sut);
fooFactory.Verify();
}
Obviously this test fails as the constructor to the Sut runs before I am able to setup the IFooFactory. So I thought that I may have been able to change the declaration of the Sut to Lazy<Sut> in the test.
But again the constructor is still run before the actual test code is run meaning that my test is going to fail.
Now I know that I could easily setup this test with an actual Fixture object and create all of my objects manually and setting them up before I call to create the Sut which is fine but I'm wanting to keep my tests all roughly the same therefore I'm wondering if there is a way that I could still setup my test with the AutoData attribute but not run the constructor until after everything is setup?
AutoFixture was originally build as a tool for Test-Driven Development (TDD), and TDD is all about feedback. In the spirit of GOOS, you should listen to your tests. If the tests are hard to write, you should consider your API design. AutoFixture tends to amplify that sort of feedback, which may also be the case here.
Consider the invariants of the Sut class. Since it has a read-only IFoo class field, I'd interpret this as a strong indication that IFoo is a dependency of the class.
If that's the case, then inject IFoo via the constructor, instead of IFooFactory:
public class Sut
{
private readonly IFoo foo;
public Sut(IFoo foo)
{
this.foo = foo;
}
public IFoo Foo
{
get { return this.foo; }
}
}
You can still compose it using IFooFactory in the application's Composition Root:
var sut = new Sut(aFactory.Build(1, 2));
This will make the tests easier to write. I can't even show you how the above test would look with this refactoring, because it'd be redundant and can (and should) be deleted.
FWIW, the original design proposed above violates Nikola Malovic's 4th law of IoC that constructors should do no work.
You can use the Fixture object pattern.
This allows you to setup your mocks before creating the sut.
Something in the lines of:
private class Fixture
{
public Mock<FooFactory> FooFactoryMock { get; set; } = new Mock<FooFactory>();
public Sut GetSut()
{
return new Sut(FooFactoryMock.Object);
}
}
[Theory]
[AutoData]
internal void Foo_IsCorrectlySet_Test(
IFoo foo)
{
var fixture = new Fixture();
fixture.FooFactory.Setup(mock => mock.Build(1, 2))
.Returns(foo)
.Verifiable();
var sut = fixture.GetSut();
var actual = sut.Foo;
Assert.Equal(foo, sut);
fooFactory.Verify();
}
You can use [Frozen] Attribute to freeze Moq dependency or try out write your own [CustomAttribute] to control dependencies.

nsubstitute giving exception while creating substitute

We are Trying to integrate Nunit testing within our web application. here we are using Nsubstitute as a mocking framework.
The project architecture goes as below:
Public class BaseService : Glass.Mapper.Sc.SitecoreContext
{
public BaseService(){}
}
Public class DerivedService : BaseService
{
IGenericRepository<Item> _genericRepository;
public DerivedService ( IGenericRepository<Item> _repository)
{
_genericRepository= _repository;
}
public string DoSomethig(){}
}
Now to test the DoSomething() method of my DerivedService class i am creating the substitue of my repository and faking its response. which should let me test my service code.
[Test]
public void TestDoSomethigMethod()
{
var repository = Substitute.For<IGenericRepository<Item>>();
DerivedService tempService = new DerivedService(repository);
// Throws an exception of type System.Collections.Generic.KeyNotFoundException : The given key was not present in the dictionary. at base service constructor.
var response = tempService.DoSomething();
}
When i try to invoke the instance of derived service it throws me the exception at baseService constructor saying (The given key was not present in the dictionary)
we are using windsor castle for dependency injection & the Base Class inherits from Glass Mapper sitecore context class.
Please let me know if anyone faced any such problem or have a solution for this.
edit: code for test case updated as suggested by Pavel & Marcio.
NSubstitute will proxy public and virtual methods/properties only. You should either substitute interfaces or make sure the classes you substitute expose public virtual methods. As far as I can tell, yours are not virtual and while NSubstitute can create the object, it can't effectively proxy/mock anything on it.
Also, if your constructor is not parameter-less make sure you are providing a substitute (or a real instance) for every argument when substituting.
More details here: http://nsubstitute.github.io/help/creating-a-substitute/
You should not create a substitute for DerivedService, but for IGenericRepository<Item> and inject it into DerivedService.
You'll only create substitutes for the parts you want to mock, not the ones you want to test.
Here's what you should do:
[Test]
public void TestDoSomethigMethod()
{
var repository = Substitute.For<IGenericRepository<Item>>();
// Here you set up repository expectations
DerivedService tempService = new DerivedService(repository);
var response = tempService.DoSomething();
// Here you assert the response
}

NUnit/Moq: I have mocked a class but real contructor is executed, why?

I have a large legacy WPF project that I'm now trying to get unit tested with NUnit (v. 2.6.3) and Moq (v. 4.2), but I'm having trouble with mocking certain classes. There's one in particular, a control class derived from System.Windows.Forms.Integration.WindowsFormsHost, that's needed all over the project and has a lot of external dependencies, so it's very important to be able to mock it.
Let's call that class Foo, and here's the test case:
[TestFixture,RequiresSTA]
public class TestMainWindowViewModel {
[Test]
public void Test1() {
var mockRepository = new MockRepository(MockBehavior.Loose) { DefaultValue = DefaultValue.Empty };
var mockFoo = mockRepository.Create<Foo>();
var sut = new MainWindowViewModel(mockFoo.Object);
}
}
My problem is that for some weird reason, while evaluating parameter mockFoo.Object in the last line, we go straight inside the constructor of the concrete class Foo! I have confirmed that this really happens with debugger, and also, the test run crashes with an error of not finding the DLL's the concrete implementation depends on.
Any ideas what could be causing this? As far as I understand, there should be NO connection to the concrete implementation here!
Thanks in advance for any advice!
-Seppo
Any ideas what could be causing this? As far as I understand, there should be NO connection to the concrete implementation here!
Moq creates its objects (mocks) by deriving from concrete implementation (your case) or implementing interface (typical, more common case):
// implement interface
var mock1 = new Mock<IService>();
// derive from ServiceImplementation
var mock2 = new Mock<ServiceImplementation>();
This is how underlying mechanisms work -- in order to create mock, Moq will have to dynamically create new type representing that mock, either by implementing interface or deriving from base class. Which means your Foo constructor should and is executed. This is how it works.
Since this is legacy code class (Foo) I suggest wrapping it with new, mockable interface and make your code depend on this interface instead:
interface IFoo
{
void DoFoo();
}
class FooWrapper : IFoo
{
private readonly Foo legacyFoo;
public FooWrapper(Foo legacyFoo)
{
this.legacyFoo = legacyFoo;
}
public void DoFoo()
{
legacyFoo.DoFoo();
}
}
Your new (non-legacy) code should depend on IFoo, not Foo and you'll be good to go.

moq a class that IS derived from the same interface as the one being moq'd

I am new to the whole MOQ movement... which by the way is pretty cool ... and I am mocking all kinds of stuff now..
Anyway, I ran into this scenario and was wondering how to go about mocking it up.
I have an class that implements the interface that I want to mock:
public interface ImyInterface
{
void doit();
}
public abstract class myBase<TChannel> : ICommunicationObject, IDisposable where TChannel : class
{
protected TChannel Channel { get; private set; }
// ICommunicationObject implementation not shown
}
public class myIIntClass : myBase<ImyInterface>, ImyInterface
{
public myIIntClass()
{
}
public void doit()
{
Channel.doit();
}
}
I think my moq test doesn't mock anything... but I am unsure and hoping to get some insight on how to either write it correctly or refactor my class:
Here is my current MOQ test:
MyClass myClass = null;
Mock<ImyInterface> moq = new Mock<ImyInterface>();
moq.Setup(x => x.doit());
myClass = (MyClass)moq.Object;
myClass.doit();
moq.VerifyAll();
Thanks from one moqer to another... :-)
I feel like maybe you're missing the point of mocking here. You mock dependencies that exist in a unit of work you're testing. So, let's say I'm testing doit here in the concrete implementation of MyClass; I want to make sure it works right. Now, let's say that method has a dependency to another class; it calls a method on it that returns a boolean value. What I want to do is mock that class because I want to make sure that MyClass.doit behaves right when it returns true and when it returns false.
See, in the example above, what I've done is ensured that no other dependencies are affecting the code flow of MyClass.doit; I'm forcing MyClass.doit down a very specific path; I want to test that path.
The code you've created literally performs nothing because it just executes the mocked up method.
You don't mock/stub the unit under test. If you are testing the doIt(), you don't mock that, you mock its (or class) dependencies.

Categories

Resources