I'm writing some unit tests that rely on StructureMap so I want to completely reset the ObjectFactory in my [SetUp] method. This is what my [SetUp] method looks like right now:
[SetUp]
public void SetUp()
{
ObjectFactory.Initialize(initializationExpression => {});
}
This appears to reset the configuration because I can execute the ObjectFactory.WhatDoIHave() method and it does not contain any of my configuration. However, cached instances of objects are not removed and are returned in subsequent tests. Is there a way to completely reset the ObjectFactory?
I thought I might have to use ObjectFactory.EjectAllInstancesOf(), but that doesn't appear to help.
I'm using version 2.5.3.
Here is some contrived code to show what I'm talking about. I would expect this test to pass, but it doesn't.
[TestFixture]
public class TestingStructureMap
{
[Test]
public void FirstTestUsingCachedObjects()
{
ObjectFactory.Configure(configure =>
configure.ForRequestedType<ISomeInterface>()
.TheDefaultIsConcreteType<SomeImplementation>()
.CacheBy(InstanceScope.ThreadLocal)
);
ISomeInterface firstSomeInterface = ObjectFactory.GetInstance<ISomeInterface>();
Assert.AreEqual(1, firstSomeInterface.ID);
ObjectFactory.Initialize(initializationExpression => { });
ObjectFactory.EjectAllInstancesOf<ISomeInterface>();
ObjectFactory.Configure(configure =>
configure.ForRequestedType<ISomeInterface>()
.TheDefaultIsConcreteType<SomeImplementation>()
.CacheBy(InstanceScope.ThreadLocal)
);
ISomeInterface secondSomeInterface = ObjectFactory.GetInstance<ISomeInterface>();
Assert.AreEqual(2, secondSomeInterface.ID);
}
public interface ISomeInterface
{
int ID { get; }
}
public class SomeImplementation : ISomeInterface
{
private static int NumberOfInstancesCreated;
private readonly int id;
public int ID
{
get { return id; }
}
public SomeImplementation()
{
id = ++NumberOfInstancesCreated;
}
}
}
Not exactly an answer but to have you considered wrinting your test such that you do not rely on the ObjectFactory but the StructureMap container?
var c = new StructureMap.Container(ce=>
{
ce.ForRequestedType<IFoo>().TheDefaultIsConcreteType<Bar>();
});
In that case you can simply recreate the container and my guess is that it should be in pristine condition.
I've figured it out. ObjectFactory.EjectAllInstancesOf() is actually dependant on there being a configuration for T. In my code, I nullified the effectiveness of ObjectFactory.EjectAllInstancesOf() by first clearing all of the configuration. If I switch these two lines of code, it works.
This does NOT work:
ObjectFactory.Initialize(initializationExpression => { });
ObjectFactory.EjectAllInstancesOf<ISomeInterface>();
This DOES work:
ObjectFactory.EjectAllInstancesOf<ISomeInterface>();
ObjectFactory.Initialize(initializationExpression => { });
Related
I have to write tests for existing code with xUnit. Here is a simplified problem I faced with:
using Xunit;
namespace XUnitTestProject1
{
public class UnitTest1
{
[Fact]
public void Test1()
{
GlobalHanler.StaticProperty = "some value";
}
[Fact]
public void Test2()
{
Assert.Null(GlobalHanler.StaticProperty);
}
}
public static class GlobalHanler
{
public static string StaticProperty;
}
}
GlobalHandler owns another object, both are static
When I run 2 tests together, Test2 fails because it can see the value that was set in Test1.
However, when I run Test2 separately, it succeeds.
My goal is to make 2 tests pass when they run together. I need somehow to reset global static property for each test separately, but I can't change the implementation of GlobalHandler
Setting StaticProperty in each test method seems not an option, because it will affect other tests running in parallel
In order to have testable code, you should first put the logic in a class that can be created as many times as needed and then use that class across your code by passing the reference.
Your production code can always use a singleton, but having no direct references to the singleton makes it testable.
Singletons and testing do not cohabit very well due to the possible side effects and unclear dependencies.
You should avoid using static. Instead of this, create a simple class and register it in your DI container as a singleton. Then you can test it easily.
Simple example:
using Microsoft.Extensions.DependencyInjection;
public class Program
{
public static void Main()
{
var serviceProvider = new ServiceCollection()
.AddSingleton<IQueueUrlProvider, QueueUrlProvider>()
.BuildServiceProvider();
Console.WriteLine(serviceProvider.GetService<IQueueUrlProvider>().QueueUrl);
}
public interface IQueueUrlProvider
{
string QueueUrl { get; }
}
public class QueueUrlProvider : IQueueUrlProvider
{
private readonly Lazy<string> _getQueueUrlLazy;
public string QueueUrl => _getQueueUrlLazy.Value;
public QueueUrlProvider()
{
_getQueueUrlLazy = new Lazy<string>(GetQueueUrl);
}
private string GetQueueUrl()
{
// get url here
return "your queue url";
}
}
}
https://dotnetfiddle.net/JjRh4q
I moved the most frequently created mocks into extensions and helper classes to be able to reuse them in several tests. I was very surprised when it turned out that they are appently context dependent and don't work when sitting elsewhere.
This code demonstrates the issue:
void Main()
{
// Does not get the mock user.
var db = MockFactory.MockUserDatabase();
db.GetUsersAsync().GetAwaiter().GetResult().Dump(); // <-- null
// This works and gets the mock user.
var mock = Mock.Create<IUserDatabase>();
mock
.Arrange(x => x.GetUsersAsync())
.Returns(Task.FromResult(new[] { new User { Name = "John" } }));
mock.GetUsersAsync().GetAwaiter().GetResult().Dump(); // <-- mock user
}
static class MockFactory
{
public static IUserDatabase MockUserDatabase()
{
var mock = Mock.Create<IUserDatabase>();
mock
.Arrange(x => x.GetUsersAsync())
.ReturnsTask(new[] { new User { Name = "John" } });
return mock;
}
}
public static class JustMockHelpers
{
public static IAssertable ReturnsTask<TReturn>(this IAssertable assertable, TReturn value)
{
return assertable.Returns(Task.FromResult<TReturn>(value));
}
}
public interface IUserDatabase
{
Task<User[]> GetUsersAsync();
}
public class User
{
public string Name { get; set; }
}
Is there any way I can make the JustMock code encapsulated in other classes work too?
The problem here is you are using a Static MockFactory and it works when you use it directly not statically. Why Would use a static class if you are still initiating the test data each time and each time you recreate the mock? Either try to have a base testing class with this method and call it base.YourInitialiseMethod() or something like TestFixtures. If you look at documentation of JustMock they always do create inside each test case individually.
I have found a trick. You can pull it to the same static context with a Func. ReturnsTask still won't cooperate but at least the general arrangement does.
static class MockFactory
{
public static Func<IUserDatabase> MockUserDatabase
{
get
{
return () =>
{
var mock = Mock.Create<IUserDatabase>();
mock
.Arrange(x => x.GetUsersAsync())
.Returns(new[] { new User { Name = "John" } }.ToTask());
return mock;
};
}
}
}
I turned the other extension around and made it:
public static Task<T> ToTask<T>(this T obj) => Task.FromResult(obj);
Then I just call:
.Returns(new[] { new User { Name = "John" } }.ToTask())
I'm working with the FakeItEasy library to create fakes for my unit tests.
I have a ClassUnderTest on which I want to test the method MethodToTest(Data dataObject). This method is calling a method of an interface which I want to fake:
public interface IFoo
{
void Execute(Action<IDataAccess> action);
}
public class ClassUnderTest
{
private IFoo _foo;
public ClassUnderTest(IFoo foo)
{
_foo = foo;
}
public void MethodToTest(Data dataObject)
{
_foo.Execute(dataAccess => dataAccess.Update(dataObject));
}
}
public interface IDataAccess
{
void Update(Data data);
}
public class Data
{
public int Property { get; set; }
}
In my unit tests I want to check if the test method calls the interface correctly (with the correct property value):
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var foo = A.Fake<IFoo>(x => x.Strict());
A.CallTo(() => foo.Execute(dataAccess => dataAccess.Update(A<Data>.That.Matches(d => d.Property == 20))));
var cut = new ClassUnderTest(foo);
cut.MethodToTest(new Data { Property = 20 });
}
}
But something is configured wrong in this test. I get the exception:
Test method TestProject1.UnitTest1.TestMethod1 threw exception:
FakeItEasy.ExpectationException: Call to non configured method "Execute" of strict fake.
Does somebody have an idea of how I have to configure the CallTo() statement correctly?
The updated example really helps, #rhe1980.
First some notes about the test you supplied:
the A.CallTo method doesn't do anything - it's not setting up behaviour (with a .Invokes or a .Returns or even a .DoesNothing) or verifying that the method has been called (for example with .MustHaveHappened).
Comparing Actions appears to be tough. I did find some advice over at Compare Delegates Action<T>, but if it were me, I'd take a slightly different tack.
Instead of attempting to compare the Action delegate to a reference model, I figured I could emulate this by capturing the action supplied to Execute and then running it on an IDataAccess and see what the action does. Fortunately, we have FakeItEasy to help with that!
I had success with this test:
[TestMethod]
public void TestMethod1()
{
// Arrange
var foo = A.Fake<IFoo>(x => x.Strict());
var fakeDataAccess = A.Fake<IDataAccess>();
A.CallTo(() => foo.Execute(A<Action<IDataAccess>>.Ignored))
.Invokes((Action<IDataAccess> action)=>action(fakeDataAccess));
var cut = new ClassUnderTest(foo);
// Act
cut.MethodToTest(new Data { Property = 20 });
// Assert
A.CallTo(() => fakeDataAccess.Update(A<Data>.That.Matches(d => d.Property == 20)))
.MustHaveHappened();
}
I hope it helps.
If I understood your intentions correctly, you need to use something as follows:
A.CallTo(() => foo.Execute(A<Action<IDataAccess>>.Ignored).MustHaveHappened();
I have a repository with an Add method that takes an IEnumerable as parameter:
public void Add<T>(T item) where T : class, new(){}
In a unittest I want to verify that this method is called with an IEnumerable that contains exactly the same amount of elements as another IEnumerable
[Test]
public void InvoicesAreGeneratedForAllStudents()
{
var students = StudentStub.GetStudents();
session.Setup(x => x.All<Student>()).Returns(students.AsQueryable());
service.GenerateInvoices(Payments.Jaar, DateTime.Now);
session.Verify(x => x.Add(It.Is<IEnumerable<Invoice>>(
invoices => invoices.Count() == students.Count())));
}
Result of the unit test:
Moq.MockException :
Expected invocation on the mock at least once, but was never performed:
x => x.Add<Invoice>(It.Is<IEnumerable`1>(i => i.Count<Invoice>() == 10))
No setups configured.
What am I doing wrong?
From your code example you haven't set up the x => x.Add on the Moq
session.Setup(x => x.Add(It.IsAny<IEnumerable>());
Unless the Setup for x.All is meant to be x.Add? If so, you need to match the Verify and Setup exactly - a good way to do that is to extract it to a common method that returns an Expression.
EDIT: Added a sample, I have changed the signature of Add as I can't see how you could pass a collection otherwise.
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
Mock<Boo> moqBoo = new Mock<Boo>();
moqBoo.Setup(IEnumerableHasExpectedNumberOfElements(10));
// ACT
moqBoo.Verify(IEnumerableHasExpectedNumberOfElements(10));
}
private static Expression<Action<Boo>> IEnumerableHasExpectedNumberOfElements(int expectedNumberOfElements)
{
return b => b.Add(It.Is<IEnumerable<Invoice>>(ie => ie.Count() == expectedNumberOfElements));
}
}
public class Boo
{
public void Add<T>(IEnumerable<T> item) where T : class, new()
{
}
}
public class Invoice
{
}
Also, a good way to debug these things is to set your Mock up with MockBehavior.Strict and then you'll be informed by the invoked code what you need to configure.
I have this code in my app .NET application using NServiceBus:
Bus.Send<IServiceStarted>(e =>
{
e.ServiceInfo = ReadServiceInfo();
e.EventTime = DateProvider.Now;
});
How would you go about unit-testing such a code?
As long as your Bus variable is an IBus instance, you can simply provide a mocked IBus implementation to the class that contains this method, and verify that Send was called on it (with the appropriate delegate, if you so desire) after the method was invoked for testing. Beyond that, you're getting into testing Bus.Send itself, which is not something you should be doing.
public class ClassThatSendsMessages
{
private readonly IBus _bus;
public ClassThatSendsMessages(IBus bus /*, ... */)
{
_bus = bus;
/* ... */
}
public void CodeThatSendsMessage()
{
/* ... */
_bus.Send<IMyMessage>(mm => mm.Property1 = "123");
/* ... */
}
}
public class ClassThatTestsClassThatSendsMessages
{
public void CallCodeThatSendsMessage()
{
//Mock IBus object here
var objectToTest = new ClassThatSendsMessages(mockedIBus /*, ... */)
objectToTest.CodeThatSendsMessage();
//Verify that IBus mock's Send() method was called
}
}
There are two ways to approach testing the delegate's logic: you can try to break down the provided expression tree, or you can change it to a named method and pass it that way. I've never gotten deep into expressions, so I'll provide an example of the latter:
public static class MyMessageBuilder
{
public static void Build(IMyMessage message) { /* ... */ }
}
public class ClassThatTestsMyMessageBuilder
{
public void CallCodeThatBuildsMessage()
{
var message = Test.CreateInstance<IMyMessage>(MyMessageBuilder.Build);
//Verify message contents
}
}
Usage:
public class ClassThatSendsMessages
{
private readonly IBus _bus;
public static Action<IMyMessage> BuildMessage { private get; set; }
public ClassThatSendsMessages(IBus bus /*, ... */)
{
_bus = bus;
/* ... */
}
public void CodeThatSendsMessage()
{
/* ... */
_bus.Send<IMyMessage>(mm => BuildMessage (mm));
/* ... */
}
}
I'm not aware of a container that can do delegate injection to constructors, but then I haven't looked very hard either, so that might be an even better way of setting the delegate.
EDIT
As I've recently run into this issue in my own tests, and I don't really like having to pull the method out into its own builder. So I set out to discover if I could test the delegate "in place". It turns out that you can:
public class ClassThatTestsClassThatSendsMessages
{
public void CallCodeThatSendsMessage()
{
Action<IMyMessage> messageAction = null;
//Mock IBus object here
mockedIBus.Setup(b => b.Send(Args.IsAny<Action<IMyMessage>>()))
.Callback((Action<IMyMessage> a) => messageAction = a);
var myMessage = Test.CreateInstance<IMyMessage>();
var objectToTest = new ClassThatSendsMessages(mockedIBus /*, ... */)
//Run the code that sends the message
objectToTest.CodeThatSendsMessage();
//Run the code that populates the message
messageAction(myMessage);
//Verify expectations on Setups
//Verify the message contents;
}
}
There are tradeoffs here - pulling the message builder out into an interface is certainly more compliant with SRP than leaving it as an inline delegate (as the test clearly demonstrates: you have to Act twice in order to test all the code). However, it presents benefits in both code size and readability.
Additionally, this code is Moq-specific; I don't know whether it's possible to get the delegate back from a RhinoMocks mock, or what the syntax would be for that.
Check out the test framework that comes with NSB, it's using Rhino underneath: http://nservicebus.com/UnitTesting.aspx. there are several samples in the download that use it with NUnit. You can get it to work under MSTest as well.