Method I am unit testing checks for a session variable like
if(Session["somevar"] != null)
{
// rest of the code
}
In my test, not able to get rid of this since Session is null, it's throwing null referrence exception.
To bypass this, I have tried mocking it like below but no luck
System.Web.Moles.MHttpContext.AllInstances.SessionGet = (HttpContext cntx) =>
{ return (HttpSessionState)cntx.Session["somevar"]; }
I even tried method mention here to simulate HttpContext and then doing below
HttpContext.Current = new HttpContext(workerRequest);
HttpContext.Current.Session["somevar"] = value;
But again no luck. This time, though the HttpContext.Current is not null but HttpContext.Current.Session and hence throws null ref exception.
Any idea how can I mock this/by pass this in my test [Without using any external DLL or main code change. Sorry, but can't afford to do so].
Thanks and appreaciate lot your help.
Update 2013:
The bad news now is that the Moles framework was a Microsoft Research (MSR) project, and will not be supported in Visual Studio 2012. The great news is that Microsoft has now integrated the MSR project into the mainline framework as Microsoft Fakes.
I found an article that solves the problem you had, using the Fakes framework instead of the Moles framework:
http://blog.christopheargento.net/2013/02/02/testing-untestable-code-thanks-to-ms-fakes/
Here's an updated version of my previous answer that uses the Fakes framework instead of Moles.
using System.Web.Fakes;
// ...
var sessionState = new Dictionary<string, object>();
ShimHttpContext.CurrentGet = () => new ShimHttpContext();
ShimHttpContext.AllInstances.SessionGet = (o) => new ShimHttpSessionState
{
ItemGetString = (key) =>
{
object result = null;
sessionState.TryGetValue(key, out result);
return result;
}
};
You might even be able to make it look more like the Moles version I posted before, though I haven't tried that out yet. I'm just adapting the article's code to my answer :)
Before 2013 edit:
You said you want to avoid changing the code under test. While I think it should be changed, as directly accessing session state like that is a bad idea, I can understand where you're coming from (I was in test once...).
I found this thread describing how someone moled both HttpContext and HttpSessionState to get around this problem.
Their code ended up looking like this:
MHttpContext.CurrentGet = () => new MHttpContext
{
SessionGet = () => new MHttpSessionState
{
ItemGetString = (key) =>
{
if (key == "some")
return "someString"/* or any other object*/;
else return null;
}
}
};
I'd go even farther and implement ItemGetString with a dictionary:
var sessionState = new Dictionary<string, object>();
MHttpContext.CurrentGet = // ...
{
// ...
ItemGetString = (key) =>
{
object result = null;
sessionState.TryGetValue(key, out result);
return result;
}
Before edit:
I usually solve problems like this by encapsulating global state with an abstract class or interface that can be instanced and mocked out. Then instead of directly accessing the global state, I inject an instance of my abstract class or interface into the code that uses it.
This lets me mock out the global behavior, and makes it so my tests don't depend on or exercise that unrelated behavior.
Here's one way to do that (I'd play with the factoring a bit tho):
public interface ISessionContext
{
object this[string propertyName] { get; set; }
}
public class ServerContext : ISessionContext
{
public object this[string propertyName]
{
get { return HttpContext.Current.Session[propertyName]; }
set { HttpContext.Current.Session[propertyName] = value; }
}
}
public class SomeClassThatUsesSessionState
{
private readonly ISessionContext sessionContext;
public SomeClassThatUsesSessionState(ISessionContext sessionContext)
{
this.sessionContext = sessionContext;
}
public void SomeMethodThatUsesSessionState()
{
string somevar = (string)sessionContext["somevar"];
// todo: do something with somevar
}
}
This would require changes to your code-under-test, but it is the type of change that is good both for testability and for portability of the code.
Related
I am writing some unit tests for a method that uploads a file using SSH.Net.
The project is a WPF app and uses Caliburn.Micro as MVVM framework and also to inject the following object in the constructor of the class I am testing:
private IFileTransferManager _fileTransferManager;
public FileUploadViewModel(IFileTransferManager fileTransferManager) : base(eventAggregator)
{
_fileTransferManager = fileTransferManager;
}
In the test project I am mocking IFileTransferManager:
private Mock<IFileTransferManager> _fileTransferManager = new Mock<IFileTransferManager>();
But now I got to the point, when in code I need to ask for a new instance of IFileTransferManager from IoC container, IoC being a static class in Caliburn.Micro:
_fileTransferManager = IoC.Get<IFileTransferManager>();
await _fileTransferManager.UploadFile(connection, file.FullName, destinationPath).ConfigureAwait(false);
How can I refactor the above code to make it testable, because currently it throws System.InvalidOperationException in Caliburn.Micro.dll due to the fact that I am re-instantiating _fileTransferManager?
I would probably do something like this, assuming there are other limiting factors that mean you want to change as little outward detail about the class as possible (note: I haven't tested this so may have to tweak a little)
public class ClassIAmTesting
{
//Have a Func to fetch a file manager...
private Func<IFileTransferManager> _filemgr = null;
//Have a property which we'll use in this class to get the File manager
public Func<IFilterTransferManager> GetFileManager
{
get
{
//If we try to use this property for the first time and it's not set,
//then set it to the default implementation.
if (_fileMgr == null)
{
_fileMgr = () => IoC.Get<IFileTransferManager>();
}
return _fileMgr;
}
set
{
//allow setting of the function which returns an IFileTransferManager
if (_fileMgr == null)
{
_fileMgr = value;
}
}
}
//this is the method you ultimately want to test...
public async Task<bool> SomeMethodIAmTesting()
{
//don't do this any more:
//_fileTransferManager = IoC.Get<IFileTransferManager>();
//instead do this.
_fileTransferManager = GetFileManager();
await _fileTransferManager
.UploadFile(connection, file.FullName, destinationPath)
.ConfigureAwait(false);
return true;
}
}
Then in your testing:
Mock<IFileTransferManager> _fileTransferManager = new Mock<IFileTransferManager>();
var cut = new ClassIAmTesting();
//not used Moq for a long time, but think you have to access .Object to get to the
//actual implementation of IFileTransferManager?
cut.GetFileManager = () => _fileTransferManager.Object;
//Do actual tests..
var result = cut.SomeMethodIAmTesting();
//Do assertions...
I suggest this approach because:
It provides a way of overriding the way the class gets the IFileTransferManager for testing
It 'falls back' to the default implementation if this override is not used, preserving the original behaviour - you don't need to change existing calls to this class at all from non-testing code
It does not change the Constructor or add a new one, which I assume is a problem since you don't simply inject an instance of the IFileTransferManager in.
one improvement might be to make the set internal which would prevent other projects from setting this method, and it could then be exposed via InternalVisibleTo or similar, but I'm trying to keep the scope fairly tight...
Inject a factory using a Func<TResult> delegate.
private readonly Func<IFileTransferManager> fileTransferManagerFactory;
public FileUploadViewModel(Func<IFileTransferManager> fileTransferManagerFactory) : base(eventAggregator) {
this.fileTransferManagerFactory = fileTransferManagerFactory;
}
This would allow for as many instances as needed being created when uploading
//get an instance using factory delegate
var fileTransferManager = fileTransferManagerFactory();
await fileTransferManager.UploadFile(connection, file.FullName, destinationPath).ConfigureAwait(false); IoC.Get<IFileTransferManager>();
For unit testing a function can be easily created to provid as many mocks needed for the test case
I was to test a method and I got everything working except for the fact I'm not able to moq the ConfigurationManager.AppSettings.
My method is defined as
public async Task<IDictionary<string, object>> Action(IDictionary<string, object> context)
{
if (ConfigurationManager.AppSettings[ApplicationUserFromDomainUserKey] == null)
throw new ConfigurationErrorsException(ApplicationUserFromDomainUserKey);
string storedProcedure = ConfigurationManager.AppSettings.Get(ApplicationUserFromDomainUserKey);
if (ConfigurationManager.ConnectionStrings[DbConnectionKey] == null)
throw new ConfigurationErrorsException(DbConnectionKey);
...
}
I've seen in this question that an approach using the facade approach would be nice but it would dirt my class implementation which doesn't make use of IoC / DI
I've read as well this intresting article but this only applies to Vs Enterprise edition and I wish it to be runnable on CI/ VS professional edition
I'm using NUnit for testing and my test is
[Test]
public void MissingAppSettingsKey()
{
var pipeline = new RetrieveApplicationUsernamePipelineStep();
var context = new Dictionary<string, object>()
{
[Resources.DomainUser] = "andrea",
[Resources.Domain] = "ifinformatica.net",
[Resources.ApplicationId] = 0
};
Assert.ThrowsAsync<ConfigurationErrorsException>(async () => await pipeline.Action(context));
}
}
P.S. I also use resharper's tools for testing which excludes me to run the microsoft unit test framework as well
The simpler approach would be to start using a limited implementation of DI to remove the ConfigurationManager dependency.
Overload your constructor (whatever it was) to take the AppSettings entries as parameters.
So if you created your object like so:
MyObject myObj = new MyObject(SomeParam);
..with constructor declaration of...
public MyObject(ParamObj someParam)
{
//...implementation....
}
...overload it like so...
public MyObject(ParamObj someParam)
: this(someParam, Convert.ToInt32(ConfigurationManager.AppSettings["mySetting"]))
{
//...implementation....
}
public MyObject(ParamObj someParam, int mySettingValue)
{
//...implementation....
}
This means when you test, you construct objects using the constructor which does not call/require ConfigurationManager.
I am working to mock up behaviors related to the StackExchange.Redis library, but can't figure out how to properly mock the sealed classes it uses. A specific example is in my calling code I'm doing something like this:
var cachable = command as IRedisCacheable;
if (_cache.Multiplexer.IsConnected == false)
{
_logger.Debug("Not using the cache because the connection is not available");
cacheAvailable = false;
}
else if (cachable == null)
{
The key line in there is _cache.Multiplexer.IsConnected where I'm checking to make sure I have a valid connection before using the cache. So in my tests I want to mock up this behavior with something like this:
_mockCache = new Mock<IDatabase>();
_mockCache.Setup(cache => cache.Multiplexer.IsConnected).Returns(false);
However, while that code compiles just fine, I get this error when running the test:
I have also tried mocking the multiplexer class itself, and providing that to my mocked cache, but I run into the fact the multiplexer class is sealed:
_mockCache = new Mock<IDatabase>();
var mockMultiplexer = new Mock<ConnectionMultiplexer>();
mockMultiplexer.Setup(c => c.IsConnected).Returns(false);
_mockCache.Setup(cache => cache.Multiplexer).Returns(mockMultiplexer.Object);
...but that results in this error:
Ultimately I want to control whether that property is true or false in my tests, so is there a correct way to mock up something like this?
Use the interface IConnectionMultiplexer instead of the concrete class ConnectionMultiplexer in your own class.
public interface ICacheable
{
void DoYourJob();
}
public sealed class RedisCacheHandler : ICacheable
{
private readonly IConnectionMultiplexer multiplexer;
public RedisCacheHandler(IConnectionMultiplexer multiplexer)
{
this.multiplexer = multiplexer;
}
public void DoYourJob()
{
var database = multiplexer.GetDatabase(1);
// your code
}
}
Then you could easily mock and test it:
// Arrange
var mockMultiplexer = new Mock<IConnectionMultiplexer>();
mockMultiplexer.Setup(_ => _.IsConnected).Returns(false);
var mockDatabase = new Mock<IDatabase>();
mockMultiplexer
.Setup(_ => _.GetDatabase(It.IsAny<int>(), It.IsAny<object>()))
.Returns(mockDatabase.Object);
var cacheHandler = new RedisCacheHandler(mockMultiplexer.Object);
// Act
cacheHandler.DoYourJob();
// Assert
// your tests
The best approach in my opinion is to wrap all of your Redis interaction in your own class and interface. Something like CacheHandler : ICacheHandler and ICacheHandler. All of your code would only ever speak to ICacheHandler.
This way, you eliminate a hard dependency on Redis (you can swap out the implementation of ICacheHandler as you please). You can also mock all interaction with your caching layer because it's programmed against the interface.
You should not test StackExchange.Redis directly - it is not code you've written.
Not included in the above answer is the more detailed Setup of the mockDatabase instance. I struggled a little bit finding a working example of something as simple as mocking the IDatabase StringGet method (e.g., handling of optional parameters, using RedisKey vs string, using RedisValue vs string, etc.), so thought I would share. Here is what worked for me.
This test setup:
var expected = "blah";
RedisValue expectedValue = expected;
mockDatabase.Setup(db => db.StringGet(It.IsAny<RedisKey>(), It.IsAny<CommandFlags>()))
.Returns(expectedValue);
To affect what is returned by this tested method call:
var redisValue = _connectionMultiplexer.GetDatabase().StringGet(key);
I have solved this problem by using a connection provider class to create the instance of the ConnectionMultiplexer. The connection provider class can simply be injected into your cache service. The benefit of this approach is that the connection provider is the only code not tested (basically a single line of someone else's code) and your cache service can be tested by mocking the injected interfaces as normal.
In the code below my cache service can be tested and only the connection provider class needs to be excluded from code coverage.
public interface IElastiCacheService
{
Task<string> GetAsync(string key);
Task SetAsync(string key, string value, TimeSpan expiry);
}
public class ElastiCacheService : IElastiCacheService
{
private readonly ElastiCacheConfig _config;
private readonly IConnectionMultiplexer _connection = null;
public ElastiCacheService(
IOptions<ElastiCacheConfig> options,
IElastiCacheConnectionProvider connectionProvider)
{
_config = options.Value;
_connection = connectionProvider.GetConnection(_config.FullAddress);
}
public async Task<string> GetAsync(string key)
{
var value = await _connection.GetDatabase().StringGetAsync(key, CommandFlags.PreferReplica);
return value.IsNullOrEmpty ? null : value.ToString();
}
public Task SetAsync(string key, string value, TimeSpan expiry) =>
_connection.GetDatabase().StringSetAsync(key, value, expiry);
}
public interface IElastiCacheConnectionProvider
{
IConnectionMultiplexer GetConnection(string endPoint);
}
[ExcludeFromCodeCoverage]
public class ElastiCacheConnectionProvider : IElastiCacheConnectionProvider
{
public IConnectionMultiplexer GetConnection(string endPoint) =>
ConnectionMultiplexer.Connect(endPoint);
}
I am stuck at this point of code that I do not know how to mock:
ConfigurationManager.AppSettings["User"];
I have to mock the ConfigurationManager, but I don't have a clue, I am using Moq.
Someone can give me a tip? Thanks!
I am using AspnetMvc4. A moment ago I wrote
ConfigurationManager.AppSettings["mykey"] = "myvalue";
in my test method and it worked perfectly.
Explanation: the test method runs in a context with app settings taken from, typically a web.config or myapp.config. ConfigurationsManager can reach this application-global object and manipulate it.
Though: If you have a test runner running tests in parallel this is not a good idea.
I believe one standard approach to this is to use a facade pattern to wrap the configuration manager and then you have something loosely coupled that you have control over.
So you would wrap the ConfigurationManager. Something like:
public class Configuration: IConfiguration
{
public string User
{
get
{
return ConfigurationManager.AppSettings["User"];
}
}
}
(You can just extract an interface from your configuration class and then use that interface everywhere in your code)
Then you just mock the IConfiguration. You might be able to implement the facade itself in a few different ways. Above I chose just to wrap the individual properties. You also obtain the side benefit of having strongly typed information to work with rather than weakly typed hash arrays.
Maybe is not what you need to accomplish, but have you considered to use an app.config in your test project?
So the ConfigurationManager will get the values that you put in the app.config and you don't need to mock anything.
This solution works nice for my needs, because I never need to test a "variable" config file.
You can use shims to modify AppSettings to a custom NameValueCollection object. Here is an example of how you can achieve this:
[TestMethod]
public void TestSomething()
{
using(ShimsContext.Create()) {
const string key = "key";
const string value = "value";
ShimConfigurationManager.AppSettingsGet = () =>
{
NameValueCollection nameValueCollection = new NameValueCollection();
nameValueCollection.Add(key, value);
return nameValueCollection;
};
///
// Test code here.
///
// Validation code goes here.
}
}
You can read more about shims and fakes at, Isolating Code Under Test with Microsoft Fakes. Hope this helps.
Have you considered stubbing instead of mocking? The AppSettings property is a NameValueCollection:
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
// Arrange
var settings = new NameValueCollection {{"User", "Otuyh"}};
var classUnderTest = new ClassUnderTest(settings);
// Act
classUnderTest.MethodUnderTest();
// Assert something...
}
}
public class ClassUnderTest
{
private readonly NameValueCollection _settings;
public ClassUnderTest(NameValueCollection settings)
{
_settings = settings;
}
public void MethodUnderTest()
{
// get the User from Settings
string user = _settings["User"];
// log
Trace.TraceInformation("User = \"{0}\"", user);
// do something else...
}
}
The benefits are a simpler implementation and no dependency on System.Configuration until you really need it.
I fear I need to recall what I said. ConfigurationManager.AppSettings sporadically behaves strange, like if it would not always immediately yield the values just written. We had sporadic unit test failures on our build machines due to this. I had to rewrite my code to use a wrapper, returning ConfigurationManager.AppSettings in the usual case and test values in unit tests.
How about just setting what you need? Because, I don't want to mock .NET, do I...?
System.Configuration.ConfigurationManager.AppSettings["myKey"] = "myVal";
You probably should clean out the AppSettings beforehand to make sure the app only sees what you want it to.
That is a static property, and Moq is designed to Moq instance methods or classes that can be mocked via inheritance. In other words, Moq is not going to be any help to you here.
For mocking statics, I use a tool called Moles, which is free. There are other framework isolation tools, like Typemock that can do this too, though I believe those are paid tools.
When it comes to statics and testing, another option is to create the static state yourself, though this can often be problematic (as, I'd imagine it would be in your case).
And, finally, if the isolation frameworks are not an option and you're committed to this approach, the facade mentioned by Joshua is a good approach, or any approach in general where you factor client code of this away from the business logic that you're using to test.
Another way to achieve this goal is to just provide your own IConfiguration, pulling from any file you'd like it to pull from, like this:
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).Build();
Now, as long as you have the values you need for testing in this JSON file, it's very easy to override and change values.
I think writing you own app.config provider is a simple task and is more useful then anything else. Especially you should avoid any fakes like shims etc. because as soon as you use them Edit & Continue no longer works.
The providers I use look like this:
By default they get the values from the App.config but for unit tests I can override all values and use them in each test independently.
There's no need for any interfaces or implement it each time over and over again. I have a utilities dll and use this small helper in many projects and unit tests.
public class AppConfigProvider
{
public AppConfigProvider()
{
ConnectionStrings = new ConnectionStringsProvider();
AppSettings = new AppSettingsProvider();
}
public ConnectionStringsProvider ConnectionStrings { get; private set; }
public AppSettingsProvider AppSettings { get; private set; }
}
public class ConnectionStringsProvider
{
private readonly Dictionary<string, string> _customValues = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
public string this[string key]
{
get
{
string customValue;
if (_customValues.TryGetValue(key, out customValue))
{
return customValue;
}
var connectionStringSettings = ConfigurationManager.ConnectionStrings[key];
return connectionStringSettings == null ? null : connectionStringSettings.ConnectionString;
}
}
public Dictionary<string, string> CustomValues { get { return _customValues; } }
}
public class AppSettingsProvider
{
private readonly Dictionary<string, string> _customValues = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
public string this[string key]
{
get
{
string customValue;
return _customValues.TryGetValue(key, out customValue) ? customValue : ConfigurationManager.AppSettings[key];
}
}
public Dictionary<string, string> CustomValues { get { return _customValues; } }
}
I want to create a simple Ninject provider that returns Moq'd instances instead of concrete types. So far I have this:
public class NinjectMockProvider<T> : IProvider
{
public static Type Type { get { return typeof(T); } }
public object Create(IContext context)
{
Mock<T> newMock = new Mock<T>();
return newMock.Object;
}
}
But this is all wrong I'm sure as I don't know what I'm doing really. Any help and code samples would be great. I just want the ability to do:
kernel.Bind<ISomeInterface>().ToProvider<NinjectMoqProvider<ISomeInterface>>();
or something to that effect.
Update
I did figure out that I could accomplish what I want by using Ninject's method binding:
kernel.Bind<ISomeInterface>().ToMethod(x => new Mock<ISomeInterface>().Object);
I still would like a more elegant way and I may have to check out Ninject.Moq as suggested by Ian, but if anyone has any real code examples that would be awesome.
Does the MockingKernel extension handle what you need? It has Moq, RhinoMocks, and NSubstitute flavors, and it is also available on NuGet.
My solution to this always just uses the following:
MoqProvider
public class MoqProvider<T> : Provider<T> // T is the desired service
{
protected override T CreateInstance(IContext context)
{
return new Mock<T>().Object;
}
}
I then also register an IMissingBindingResolver with my kernel. The MoqMissingBindingResolver simply creates a new binding to a MoqProvider for any service for which a binding does not already exist.
MoqMissingBindingResolver
public class MoqMissingBindingResolver : NinjectComponent, IMissingBindingResolver
{
public IEnumerable<IBinding> Resolve(Multimap<Type, IBinding> bindings, IRequest request)
{
if (request.Service.IsAbstract || request.Service.IsInterface)
{
var moqProvider = (IProvider)Activator.CreateInstance(typeof(MoqProvider<>).MakeGenericType(request.Service));
return new IBinding[]
{
new Binding(request.Service, new BindingConfiguration
{
ProviderCallback = ctx => moqProvider,
ScopeCallback = Settings.DefaultScopeCallback
})
};
}
else
{
return Enumerable.Empty<IBinding>();
}
}
}
I typically also set Settings.DefaultScopeCallback to singleton so that I can request my mocked objects in my tests later on when I need to verify certain calls have or haven't taken place, or setup behaviour on mocks prior to executing the test. So setting up my kernel will look like the following:
INinjectSettings Settings = new NinjectSettings
{
DefaultScopeCallback = StandardScopeCallbacks.Singleton
};
var k = new StandardKernel(Settings);
k.Components.Add<IMissingBindingResolver, MoqMissingBindingResolver>();
Hope this is helpful.