We are looking at adding unit tests to our C# code base. I am finding it easy to add unit tests to simple classes, but classes that interact with other dependencies are more difficult. I have been looking at mocking frameworks, but was wondering about the best approach to write classes in the first place to break external dependencies, like file system, database and messaging system dependencies.
To give an example, a routine listens on a socket for a message in a certain format - say MessageA. This is decoded, some calculations are done, this is re-encoded into a different binary format and the resulting message then sent, MessageB.
My current testing approach is as follows. I extract an interface for all socket interactions, and create a mock interface. I set the interface in a singleton. Then run the class against hard coded inputs. The class under test will use the interface in the singleton to send/receive.
I do a similar thing to test database interactions.
This does not seem like the most flexible approach, how would you go about improving this to make it easier to test? If a mocking framework is the answer, how would I design the classes?
Example code :
[SetUp]
public void init()
{
// set message interface in singleton as mock interface
CommAdapter.Instance.MessageAdapter = new MockMessage();
// build reference message from hard coded test variables
initialiseMessageA();
// set input from mock message socket
((MockMessage) CommAdapter.Instance.MessageAdapter).MessageIn = m_messageA;
}
[Test]
public void test_listenMessage_validOutput()
{
// initialise test class
MessageSocket tS = new MessageSocket();
// read from socket
tS.listenMessage();
// extract mock interface from singleton
MockMessage mm = ((MockMessage) CommAdapter.Instance.MessageAdapter);
// assert sent message is in correct / correstpoinding format
Assert.AreEqual(1000001, mm.SentMessageB.TestField);
}
Instead of using Singletons to set your component implementations, use a Dependency Injection, and a DI library like Ninject. This is exactly the type of scenario they were designed for.
Not pushing you to Ninject specifically, but they have a good tutorial :) The concepts will transfer to other frameworks (like Unity).
https://github.com/ninject/ninject/wiki
With DI alone, the code will look something like this:
class Samurai {
private IWeapon _weapon;
public Samurai(IWeapon weapon) {
_weapon = weapon;
}
public void Attack(string target) {
_weapon.Hit(target);
}
}
class Shuriken : IWeapon {
public void Hit(string target) {
Console.WriteLine("Pierced {0}'s armor", target);
}
}
class Program {
public static void Main() {
Samurai warrior1 = new Samurai(new Shuriken());
Samurai warrior2 = new Samurai(new Sword());
warrior1.Attack("the evildoers");
warrior2.Attack("the evildoers");
}
}
This looks clean now, but wait until your dependencies have dependencies, or further :) You can use a DI library to solve that, though.
With a library to handle the wiring up for you, it will look something like:
class Program {
public static void Main() {
using(IKernel kernel = new StandardKernel(new WeaponsModule()))
{
var samurai = kernel.Get<Samurai>();
warrior1.Attack("the evildoers");
}
}
}
// Todo: Duplicate class definitions from above...
public class WarriorModule : NinjectModule {
public override void Load() {
Bind<IWeapon>().To<Sword>();
Bind<Samurai>().ToSelf().InSingletonScope();
}
}
With either of these approaches, plus a mock object framework like Moq, your unit tests look something like this:
[Test]
public void HitShouldBeCalledByAttack()
{
// Arrange all our data for testing
const string target = "the evildoers";
var mock = new Mock<IWeapon>();
mock.Setup(w => w.Hit(target))
.AtMostOnce();
IWeapon mockWeapon = mock.Object;
var warrior1 = new Samurai(mockWeapon);
// Act on our code under test
warrior1.Attack(target);
// Assert Hit was called
mock.Verify(w => w.Hit(target));
}
You'll notice you can just pass mock instances straight into the code under test, and you don't have to mess around with setting singletons. This will help you avoid problems like needing to set up the state multiple times, or in between calls. It means no hidden dependencies.
You'll also notice I didn't use the DI container in the tests. If your code is well factored, it will only be testing a single class (and as often as possible, only a single method), and you will only need to mock out the direct dependencies of that class.
In addition to a DI container (I'm using MS Unity 2.0 currently but there are many to choose from) you will need a good mocking framework, my preference is MOQ. A common pattern/process for breaking concrete dependencies is:
define the dependency via an interface; you may luck out and already have an interface, like IDbConnection or you may need to use Proxy to wrap a concrete type and define your own interface.
resolve the concrete implementation via your DI container
inject your mock implementations into your DI container at test setup time (inject real impls. at system startup)
Related
I have an application that creates a lifetime scope at some point like so:
public class Main
{
public void Main()
{
using (ILifetimeScope scope = AutofacContainer.Container.BeginLifetimeScope())
{
scope.Resolve<SomeClass>();
}
}
}
Within SomeClass I have logic which then calls a lot of different classes and so on..
Then, about 10 methods down the call stack I need to use the main scope to do this:
public class ActivatorFactory : IActivatorFactory
{
public T Create<T>(Type instance)
{
using (ILifetimeScope scope = AutofacContainer.Container.BeginLifetimeScope())
{
return (T)scope.Resolve(instance);
}
}
}
The problem with that is that now I've created a new scope which is just used to resolve a runtime type. I want to be able to use the main scope to resolve this type. How can I do so without passing the main scope down to this factory class through 10 different methods/functions?
The only "hacky" solution I thought of is to just have a static property on my ActivatorFactory and set the scope in my Main class like so:
public class Main
{
public void Main()
{
using (ILifetimeScope scope = AutofacContainer.Container.BeginLifetimeScope())
{
ActivatorFactory.Scope = scope;
scope.Resolve<SomeClass>();
}
}
}
Is there a cleaner solution to use the main scope in another part of my application?
I had this need for a CancellationTokenSource instance per lifetime scope, where children are linked to their parent. If the the root scope's CancellationTokenSource, is canceled, all children lifetime scope's CancellationToken are canceled. To accomplish this, I created:
private sealed class ParentLifetimeScopeAccessor
{
private readonly ILifetimeScope _lifetimeScope;
public ParentLifetimeScopeAccessor(ILifetimeScope lifetimeScope)
{
_lifetimeScope = lifetimeScope;
_lifetimeScope.ChildLifetimeScopeBeginning += OnChildLifetimeScopeBeginning;
}
public ILifetimeScope ParentLifetimeScope { get; private set; }
private void OnChildLifetimeScopeBeginning(object sender, LifetimeScopeBeginningEventArgs e) =>
e.LifetimeScope.Resolve<ParentLifetimeScopeAccessor>().ParentLifetimeScope = _lifetimeScope;
}
With a registration, you can now access your parent's scope:
builder.RegisterType<ParentLifetimeScopeAccessor>().InstancePerLifetimeScope();
With the parent lifetime scope accessor, linked CancellationTokenSource instances can be created:
private static CancellationTokenSource CancellationTokenSourceFactory(IComponentContext context)
{
var scopeAccessor = context.Resolve<ParentLifetimeScopeAccessor>();
var parentScope = scopeAccessor.ParentLifetimeScope;
return null == parentScope
? new CancellationTokenSource()
: CancellationTokenSource.CreateLinkedTokenSource(parentScope.Resolve<CancellationTokenSource>().Token);
}
CancellationToken resolver:
private static CancellationToken CancellationTokenResolver(IComponentContext context) =>
context.Resolve<CancellationTokenSource>().Token;
Two registrations:
builder.Register(CancellationTokenSourceFactory).AsSelf().InstancePerLifetimeScope();
builder.Register(CancellationTokenResolver).AsSelf().InstancePerDependency();
If you're not using ActivatorFactory for your app (and you shouldn't be if you're using inversion of control) then delete it and think about what you're trying to test.
Are you trying to test that you can generally just resolve things from Autofac? Autofac has a raft of unit tests as well as millions of successful users. No value in testing the framework.
Are you trying to test that you registered all the things you needed to register? There's not a lot of value in that, either, for a couple of reasons: first, you'll hit that at runtime pretty quickly and see it in those tests; second, in a large, decoupled system those tests get really stale really quickly. It's a maintenance hassle.
Are you trying to test that a specific object graph can be composed based on your registrations? I might buy this one. See below.
Let's say it's the last thing - you have a really complex and troublesome object graph you want to ensure you can create because people keep breaking it. I could see that.
Separate your registrations out into an Autofac module. Use the Autofac module to test.
public class MyRegistrations : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<Thing>();
// and all your other registrations.
}
}
then in the unit test
var builder = new ContainerBuilder();
builder.RegisterModule<MyRegistrations>();
var container = builder.Build();
var thing = container.Resolve<Thing>();
// Assert on the resolved thing.
You can use that same module to encapsulate your registrations in the app and then you'll actually be testing the complex registration but without a factory you're not using.
Warning: It is a slippery slope between testing some complex registration and testing all registrations. Like I said, you really don't want to test every registration you have. I've fallen down this slope. It's a maintenance nightmare. Add a registration to the module/app, add a test. Uh oh, we refactored, now the registrations are all different. Ugh. That's less testing about behavior than about characterization (not "what do I want it to do" but "what does it do now"). Pain. Suffering.
If you are using ActivatorFactory in your app for, say, service location instead of using some more standard thing like CommonServiceLocator that already does that for you and for which Autofac already directly integrates... then just test ActivatorFactory with a real container but with some arbitrary test registrations rather than the whole set from the real app. The functionality of ActivatorFactory doesn't have any bearing on what's registered inside it.
And, yeah, if you're using ActivatorFactory and need to keep it around, you'll have to hand it an ILifetimeScope at app startup. That's how service locators work. You'll see that all over in the Autofac docs when you look at how to integrate with apps like ASP.NET, WCF, and others.
Consider this class with these two constructors:
public class DocumentService
{
private IDocumentDbService documentDbService;
private IDirectoryService directoryService;
private IFileService fileService;
// Constructor
public DocumentService()
{
this.documentDbService = new DocumentDbService();
this.directoryService = new DirectoryInfo();
this.filService = new FileInfo();
}
// Injection Constructor
public DocumentService(IDocumentDbService dbs, IDirectoryService ds, IFileService fs)
{
this.documentDService = dbs;
this.directoryService = ds;
this.fileService = fs;
}
}
I use the second constructor to mock the dependencies for unit testing.
Some times there are too many dependencies, so the injection constructor would have too many parameters.
So, I want to use Unity dependency injection.
Question
How can I refactor this code to use Unity instead?
(After reading Unity documents, still not sure how to use it correctly on my codes.)
Assuming you want to simplify unit test code to avoid manually setting up each dependency in every test:
You can setup container and add all necessary mocks there and than Resolve you class for the test like:
// that initialization can be shared
var container = new UnityContainer();
// register all mocks (i.e. created with Moq)
container.RegisterInstnce<IDocumentDbService>(Mock.Of<IDocumentDbService> ());
// resolve your class under test
var documentService = container.Resolve<DocumentService>();
Assert.AreEqual(42, documentService.GetSomething());
I quess you want to inject dependencies in both situations: in (unit)tests (e.g. using RhinoMocks) and real implementation (using Unity). The refactoring implies in that case that you should remove the the first constructor (of class DocumentService). Needed configuration in your dependencies should be loaded inside the dependency itself: DocumentDbService, DirectoryInfo, FileInfo. More information (like Dependency Injection Lifecycle) and some examples are available on MSDN, see https://msdn.microsoft.com/en-us/library/dn178463(v=pandp.30).aspx
I've got a controller with a lot of constructor injection:
public MoviesController(ISession session, IClientContext clientContext, PManager pManager, ISegmentationService segmentationService, IGeoLocator geoLocator, IBus bus)
{
_session = session;
_clientContext = clientContext;
_pManager = pManager;
_segmentationService = segmentationService;
_geoLocator = geoLocator;
_bus = bus;
}
From my understanding (just read about Mocking), I've got a lot of Mock object properties to manually set if I wish to make a comprehensive test suite based on this controller.
For one method I'm only using one service (I'd even like to automate that with little effort if possible):
public object Show(Guid id)
{
var movie = _session.Get<movie>(id);
return movie;
}
But in another there are many services being used - is there any way to set those Moq objects up quickly? I could really use some examples as I'm new to testing. It's an asp.net mvc project with webapi 1 bundled in (testing the webapi controller here)
As has been said in the comments, if you have common setup code, you can put it in a Setup method that is called automatically from your testing framework before each test. It's decorated with a Setup attribute if you're using Nunit TestInitialize if you're using MStest. If you're using XUnit then it's a bit different.
So, your class might look like this:
public class SomeTests {
Mock<ISession> _sessionMock;
Mock<IClientContext> _clientContextMock;
[Setup]
public void Setup() {
_sessionMock = new Mock<ISession>();
_clientContextMock = new Mock <IClientContext();
}
MovieController CreateSut() {
return new MovieController(_sessionMock.Object, _clientContextMock.Object, ...);
}
[Test]
public void TestSomething() {
_sessionMock.Setup(x=>...);
//...
var sut = CreateSut();
//...
}
}
If you're trying to get away from completely creating the mocks manually, then you might want to look at something like AutoFixture with AutoMoq. Which will automatically supply mock instances when creating objects that accept interfaces. AutoFixture can be quite useful, but there is a learning curve to using it effectively so you might want to look at a tutorial / quickstart.
You could also configure an IOC container to supply mock instances for your test project, although I've never gone down that route myself.
For your example, you only need to mock the session, and can leave all the other dependencies null, since their behaviour should be irrelevant to the behaviour you are testing:
Mock<ISession> mockSession = new Mock<ISesssion>();
MoviesController controller = new MoviesController(mockSession.Object, null,null,null,null,null);
There is no need for you to set up any mocks other than the ones you need for this particular test
I have an interface which is used in an MVC controller which gets some data. To keep it simple the interface so far looks something like this:
public interface IDataProvider
{
DataModel GetData();
}
I have appropriate unit tests for this interface where it is called in the action. However, in the real implementation this will call a web service which of course could throw an exception, therefore if it does I want to write a test to ensure that I log a message if an error occurs.
To do this I have a logger interface which is actually an interface to NLog called ILogger. I could do this:
public interface IDataProvider
{
DataModel GetData(ILogger logger);
}
This would allow me to run unit tests for the logger making it nice and simple. However, I don't think this is the right way of doing this because the logger is really unrelated to this method. Also, if I start adding other methods to this interface which I need logging for then I will have to include the logger in the parameter of all of those methods as well.
The best way I can think of right now is to include the logger in the constructor of my implementation which might look like this:
public class DataProvider : IDataProvider
{
private readonly ILogger _logger;
public DataProvider(ILogger logger)
{
_logger = logger;
}
public DataModel GetData()
{
// CODE GOES HERE
}
}
However this means that I cannot test the logger in my unit tests. What is the best way to achieve this so that I can keep the logger separate from the method and make it testable?
I'll appreciate any help, thanks.
EDIT:
I realise I missed out unit testing code here is what I mean:
At the moment I am ensuring that GetData is called in my action this way:
var controller = new DataController(_dataProvider.Object);
controller.Index();
_dataProvider.Verify(dataProvider => dataProvider.GetData());
What I'd like to do is the same but for the logger but only if an exception is thrown like this:
_dataProvider.Setup(dataProvider => dataProvider.GetData()).Throws<WebException>();
var controller = new DataController(_dataProvider.Object);
controller.Index();
_logger.Verify(logger => logger.ErrorException(It.IsAny<string>(), It.IsAny<Exception>());
Obviously logger would be given to data provider in the setup. I hope that makes a bit more sense.
You can try using the factory pattern.
What happens here is in your production code, you are getting the logger from a Factory. In this factory, it returns either your real logger, or a fake logger which is setup in your unit tests. To your production code, it makes no difference what-so-ever.
In your Unit Tests, you are using a fake logger created using Moq. This fake allows you to test that an interface method was called, in this case ILogger.Log(). This is done by using the .Verify method.
Try something like this:
ILogger.cs
public interface ILogger
{
void Log(string message);
}
LoggerFactory.cs
public static class LoggerFactory
{
public static ILogger Logger
{
get
{
return LoggerFactory._logger == null ? new Logger() : LoggerFactory._logger;
}
set
{
LoggerFactory._logger = value;
}
}
private static ILogger _logger = null;
}
DataProvider.cs
public void GetData()
{
var logger = LoggerFactory.Logger;
logger.Log("..."); // etc...
}
UnitTest.cs
private void Mock<ILogger> _mockLogger = null;
public void Load()
{
this._mockLogger = new Mock<ILogger>();
LoggerFactory.Logger = _mockLogger.Object;
}
public void UnitTest()
{
// test as required
this._mockLogger.Verify(m => m.Log(It.IsAny<string>()));
}
Use a mocking framework (e.g. Moq or RhinoMocks) to verify that the logger was called. Then the final code block you post, where the logger is passed in via the constructor, will work.
Passing logger (or any other dependencies) in constructor is very standard practice and allows you to use dependency injection framework if needed.
I'm not sure why you see passing logger in constructor as limiting for unit test: you have 3 components that you can test separately
controller (depends on data provide, mock this dependency to test),
data provider (depends on logging and some other classes that let you call web service - mock all dependencies so you know when logging called and no need to call Web service)
logging - not sure what it depends on, but should be testable separately.
Notes:
use mocking framework (i.e. moq ) for your tests - you'll be able to provide any implementations of interfaces (including exceptions) very easily.
see if dependency injection framework (i.e. Unity ) would work for you. MVC4 is very well suited for it.
If you need to test that the logger is being called, I suggest using a test double called a "spy". This would not do any logging, but keep track of which methods (if any) were called. Then you can verify that the logger is called in specific instances.
You could do this by using a mocking framework to create the double (or mock) for you. Or you could create the ILogger implementation yourself. For example:
class LoggerSpy : ILogger
{
public string LogWasCalled;
public void Log(string message)
{
LogWasCalled = true;;
}
}
The following seems to have an example of mocking an ILogger using Moq: How to Mock ILogger / ILoggerService using Moq
Recently, Castle added support for interface factories with implementations provided by the kernel. I am wondering if there is a way to do this in autofac also. I have read about the delegate factories, but I think I might be missing something, and am unable to get it to work. Here is what I am thinking:
class Message { }
interface IHandle<T> {
void Handle(T message);
}
class Handle<Message> : IHandle<Message> {
...
}
class Bus {
.ctor (? lookup) {
_lookup = lookup;
}
void Send<T>(T message) {
_lookup.GetHandler<T>().Handle(message);
}
}
var builder = new ContainerBuilder();
builder.RegisterType<Handle<Message>>().As<IHandle<Message>>();
builder.RegisterType<Bus>();
var container = builder.Build();
container.Resolve<Bus>().Send<Message>(new Message());
What I'm trying to do is keep the container out of the bus (as I agree that service locator is an anti-pattern) or any other implementation. This problem is easy if I just feed the container to the bus, or create some class factory that wraps the container. Just trying to make sure there isn't a way to do this already.
Btw, the castle way iirc allows me to register something like this:
interface IHandlerFactory {
IHandle<T> GetHandler<T>();
}
container.Register<IHandlerFactory>().AsFactory();
Thanks,
Nick
You could isolate that coupling by creating a concrete IHandlerFactory, say AutofacHandlerFactory, which would receive the ILifetimeScope. That coupling seems inevitable since the container is the only one who can resolve the proper IHandler<T>.
Coupling with ILifetimeScope might be a bad idea, but then, the coupling is isolated inside the concrete IHandlerFactory, and the Bus just uses it through an interface. Let's say you change the container and starts using Ninject, you could just implement a NinjectHandlerFactory to do the job.
Seems like the answer is 'No'.
I've tried to use AggregateService which is supposed to do what you want, but it crashes during factory resolution with message 'The type "Castle.Proxies.IComponentFactoryProxy" from assembly "DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" has tried to implement an unaccessible interface.' (The original message is in Russian, I've translated it).
I can't figure out another approach that would work without a manual (yet quite simple) implementation. Maybe you should write to Nicholas Blumhardt.
In fact, I'd better do it this way:
public class Bus {
readonly ILifetimeScope _OwnScope;
// Autofac always provides ILifetimeScope that owns a component as a service to the component
// so it can be used as a dependency
public Bus(ILifetimeScope ownScope) {
_OwnScope = ownScope;
}
void Send<T>(T message) {
_OwnScope.Resolve<IHandler<T>>.Handle(message);
}
}
You will probably argue that coupling with ILifetimeScope is a bad idea. Well, it's quite a simple interface which might be wrapped into your own implementation. Or you may factor the code out into a simple factory class. Well, it seems like you know how to do this without my suggestions.