I'm trying to implement a unit test for a function in a project that doesn't have unit tests and this function requires a System.Web.Caching.Cache object as a parameter. I've been trying to create this object by using code such as...
System.Web.Caching.Cache cache = new System.Web.Caching.Cache();
cache.Add(...);
...and then passing the 'cache' in as a parameter but the Add() function is causing a NullReferenceException. My best guess so far is that I can't create this cache object in a unit test and need to retrieve it from the HttpContext.Current.Cache which I obviously don't have access to in a unit test.
How do you unit test a function that requires a System.Web.Caching.Cache object as a parameter?
When I've been faced with this sort of problem (where the class in question doesn't implement an interface), I often end up writing a wrapper with associated interface around the class in question. Then I use my wrapper in my code. For unit tests, I hand mock the wrapper and insert my own mock object into it.
Of course, if a mocking framework works, then use it instead. My experience is that all mocking frameworks have some issues with various .NET classes.
public interface ICacheWrapper
{
...methods to support
}
public class CacheWrapper : ICacheWrapper
{
private System.Web.Caching.Cache cache;
public CacheWrapper( System.Web.Caching.Cache cache )
{
this.cache = cache;
}
... implement methods using cache ...
}
public class MockCacheWrapper : ICacheWrapper
{
private MockCache cache;
public MockCacheWrapper( MockCache cache )
{
this.cache = cache;
}
... implement methods using mock cache...
}
public class MockCache
{
... implement ways to set mock values and retrieve them...
}
[Test]
public void CachingTest()
{
... set up omitted...
ICacheWrapper wrapper = new MockCacheWrapper( new MockCache() );
CacheManager manager = new CacheManager( wrapper );
manager.Insert(item,value);
Assert.AreEqual( value, manager[item] );
}
Real code
...
CacheManager manager = new CacheManager( new CacheWrapper( HttpContext.Current.Cache ));
manager.Add(item,value);
...
I think your best bet would be to use a mock object (look into Rhino Mocks).
A very useful tool for unit testing legacy code is TypeMock Isolator. It'll allow you to bypass the cache object entirely by telling it to mock that class and any method calls you find problematic. Unlike other mock frameworks, TypeMock uses reflection to intercept those method calls you tell it to mock for you so you don't have to deal with cumbersome wrappers.
TypeMock is a commercial product, but it has free versions for open-source projects. They used to have a "community" edition that was a single-user license but I don't know if that's still offered.
var httpResponse = MockRepository.GenerateMock<HttpResponseBase>();
var cache = MockRepository.GenerateMock<HttpCachePolicyBase>();
cache.Stub(x => x.SetOmitVaryStar(true));
httpResponse.Stub(x => x.Cache).Return(cache);
httpContext.Stub(x => x.Response).Return(httpResponse);
httpContext.Response.Stub(x => x.Cache).Return(cache);
Related
I am having troubles when testing a controller, because there are some lines at my Startup that are null when testing, I want to add a condition for run this lines only if it's not testing.
// Desired method that retrieves if testing
if (!this.isTesting())
{
SwaggerConfig.ConfigureServices(services, this.AuthConfiguration, this.ApiMetadata.Version);
}
The correct answer (although of no help): It should not be able to tell so. The application should to everything it does unaware if it is in productino or test.
However to test the application in a simpler setting, you can use fake modules or mock-up modules that are loaded instead of the heavy-weight production modules.
But in order to use that, you have to refactor your solution and use injection for instance.
Some links I found:
Designing with interfaces
Mock Objects
Some more on Mock objects
It really depends on which framework you use for testing. It can be MSTest, NUnit or whatever.
Rule of thumb, is that your application should not know whether it is tested. It means everything should be configured before actual testing through injection of interfaces. Simple example of how tests should be done:
//this service in need of tests. You must test it's methods.
public class ProductionService: IProductionService
{
private readonly IImSomeDependency _dep;
public ImTested(IImSomeDependency dep){ _dep = dep; }
public void PrintStr(string str)
{
Console.WriteLine(_dep.Format(str));
}
}
//this is stub dependency. It contains anything you need for particular test. Be it some data, some request, or just return NULL.
public class TestDependency : IImSomeDependency
{
public string Format(string str)
{
return "TEST:"+str;
}
}
//this is production, here you send SMS, Nuclear missle and everything else which cost you money and resources.
public class ProductionDependency : IImSomeDependency
{
public string Format(string str)
{
return "PROD:"+str;
}
}
When you run tests you configure system like so:
var service = new ProductionService(new TestDependency());
service.PrintStr("Hello world!");
When you run your production code you configure it like so:
var service = new ProductionService(new ProductionDependency());
service.PrintStr("Hello world!");
This way ProductionService is just doing his work, not knowing about what is inside it's dependencies and don't need "is it testing case №431" flag.
Please, do not use test environment flags inside code if possible.
UPDATE:
See #Mario_The_Spoon explanation for better understanding of dependency management.
I recently started tdd, but my mocking knowledge is incomplete. I know the basics but, Tests for some methods which were written without thinking tdd, really confuse me.
Here is what I am trying to test
public int GetThirdPartyUserId(int serviceTypeId, string accessToken)
{
ThirdPartyRequestDetail requestDetail = GetThirdPartyRequestDetails(serviceType, accessToken);
IHttwrapConfiguration configuration = new HttwrapConfiguration(requestDetail.BaseUrl);
IHttwrapClient httwrap = new HttwrapClient(configuration);
Task<IHttwrapResponse<OpenAuthUserResponse>> response = httwrap.GetAsync<OpenAuthUserResponse>(requestDetail.PathAndQuery);
try
{
if (response.Result.Data != null && response.Status != TaskStatus.Faulted)
{
//Do something
}
else
{
//WANT TO TEST HERE
}
}
}
Here is my test method
private Mock<IHttwrapClient> _httpwrap;
public void httprwapTest()
{
string accessToken = "invalid";
int thirdPartySiteId = (int)ThirdPartyServiceType.GooglePlus;
string requestPath = _fixture.Create<string>();
_httpwrap.Setup(item => item.GetAsync(requestPath)).Returns(Task.FromResult(new HttwrapResponse(HttpStatusCode.BadRequest, "body")));
OpenAuthUserResponse response = _oauthAuthenticator.GetThirdPartyUser(thirdPartySiteId, accessToken);
Assert.AreEqual(response.Error, OauthAuthenticatorErrorType.RequestFaulted);
}
What I tried to do is below but it didn't get triggered.
_httpwrap.Setup(item => item.GetAsync(requestPath)).Returns(Task.FromResult(new HttwrapResponse(HttpStatusCode.BadRequest, "body")));
How I can test my classes behaviour when httpwrap gives me a badrequest response code?
In it's current form, you can't use a conventional mocking framework to help with your test. In order for the Mocking to work, you have to Setup the same mock that you're using in your production code. Currently there's no connection between the mock you're creating in your test and the IHttpwrapClient that your method under test depends on.
The first step you would need to do take is to move the creation of the HttpwrapClient outside of the method that you want to test. You then need to make it available to the code, via it's interface, in a way that you can later supply it from your test.
There are three common ways of supplying the interface.
Inject it into the constructor for your class
Inject it through a property on your class
Pass it as an argument to the function
Generally constructor injection is preferred over property injection, but it's largely up to you which approach is going to work best (they each have positives and negatives) and what makes most sense for the data that you're injecting.
You would then create the Mock of your interface and inject it into your code as appropriate.
As far as your production code goes, you're still going to need to create an instance of your concrete class. You can either do this directly when calling your class, or via something like a factory, or by using an IoC container, like Castle Winsor or Ninject (there are several others).
First attempt at any real unit testing. I have a WPF client application which receives data from methods in a WCF service. These method calls are made directly from my view models in the client app:
public string LoadArticle()
{
MyServiceClient msc = new MyServiceClient();
return Article = msc.GetArticle(_UserName);
}
I then have a test project where I new up a viewmodel then call my method:
[TestMethod]
public void LoadArticleTestValid()
{
var articleViewModel = new ArticleViewModel("Thomas");
string userName = "Thomas";
string expected = "Article 1";
var actual = articleViewModel.LoadArticle(userName);
etc.
}
Obviously this test will fail because the client application cannot reach the service to invoke LoadArticle. How is this situation tackled? Do I use Dependency Injection and pass a IMyService interface of some kind into the constructor instead of creating MyServiceClient in the ViewModel or do I mock the service somehow?
This is the problem:
MyServiceClient msc = new MyServiceClient();
This creates a tight coupling between ArticleViewModel and MyServiceClient. In order to unit test just ArticleViewModel this dependency would need to be mocked. If there's an IMyServiceClient then you'd supply that to the class:
public ArticleViewModel
{
private IMyServiceClient ServiceClient { get; set; }
public ArticleViewModel(IMyServiceClient serviceClient)
{
this.ServiceClient = serviceClient;
}
// etc.
}
Then code within that class wouldn't create a new service client, it would just use the one that's in that property.
Then in the unit test you'd create a mock of IMyServiceClient, define expected behaviors on that mock, and supply it to the object being tested. How you do that depends on the mocking library. A quick example in Rhino Mocks might look like this:
// arrange
var serviceClient = MockRepository.GenerateMock<IMyServiceClient>();
serviceClient.Stub(c => c.GetArticle(Arg<string>.Is.Anything)).Return("Article 1");
var model = new ArticleViewModel(serviceClient);
// act
var result = model.LoadArticle("Thomas");
// assert
Assert.AreEqual("Article 1", result);
The idea here is that the unit test is only testing the LoadArticle method, not the dependencies invoked by that method. Those dependencies are supplied with expected behaviors and the result is examined based on those expected behaviors.
Note: There's nothing stopping the unit test from supplying the actual implementation of MyServiceClient as well, instead of a mock. The unit test project just needs the configuration for that service to work. (Unit test projects are application hosts, they can have App.config files.) This would be an integration test rather than a unit test, but the same assertions of the results can be made.
Yes, I think you are right I would suggest a constructor parameter of IMyService, which you can use to inject a mock into the object for testing.
Further! I would suggest not using the autogenerated service client. if you copy and paste the code out into your own class you can make it implement IMyService and effectivly hide the fact that it uses WCF, goes direct to the DB or is a mocked object from the real code.
this will allow you to inject your Mock into the WPF for UI testing
Here's the sample static method, say
public static void UpdateSchedule(int selectedScheduleId)
{
using (var dc = new MyDataContext())
{
var selectedSchedule = dc.Schedules.SingleOrDefault(p => p.ScheduleId == selectedScheduleId)
if selectedSchedule != null)
{
selectedSchedule.Name = name;
//and update other properties...
}
dc.SubmitChanges();
}
}
So what would be the correct approach to test on methods like this? Is there a way to avoid calling new MyDataContext() as it might increase the execution time of the unit test.
Also, I am using MsTest test framework in VS2012.
Static functions interfere with testing primarily because they:
Are difficult (sometimes impossible) to substitute from within a consumer
Tend to have "hidden" dependencies
Since you want to test the function itself, number 1 isn't an issue. However, number 2 is problematic because the static function is tightly coupled to the MyDataContext class.
If you want to test the static function without MyDataContext (that is, in isolation) you need to introduce a code seam. This requires some refactoring work, but we can do it fairly painlessly.
Consider if you had the following additional method:
public static void UpdateScheduleWithContext(int selectedScheduleId, IDataContext dc)
{
var selectedSchedule = dc.Schedules.SingleOrDefault(p => p.ScheduleId == selectedScheduleId)
if selectedSchedule != null)
{
selectedSchedule.Name = name;
//and update other properties...
}
dc.SubmitChanges();
}
This new function gives the consumer (i.e., the test) the ability to supply a test double for the data context. This is the seam.
Obviously, though, you don't want all consumers to explicitly provide a data context (which is why you had the original static function to begin with). So you can keep that function around, and just modify it:
public static void UpdateSchedule(int selectedScheduleId)
{
using (var dc = new MyDataContext())
{
UpdateScheduleWithDataContext(selectedScheduleId, dc);
}
}
If you don't have a seam like this, it will be impossible to test the function in isolation. As a result, an integration test would be the best you could hope for.
As Simon Whitehead said, it is impossible to do effective unit testing on static methods and objects. However, using the unit test framework in Visual Studio, you can create a 'unit test' function that is effectively a integration test. Tell Visual Studio to generate a Unit Test for UpdateSchedule, and then modify the function generated to set up the environment/state of the program such that the UpdateSchedule method can execute (create a database connection, instantiate classes, etc.). This includes ensuring that your database has records to update.
Once that is done, you can execute your integration test in the same manner that you would a unit test.
I've got some code that's accessing the HttpContextBase.Trace object and doing some things with it (checking IsEnabled, writing some messages). The problem is that it's a System.Web.TraceContext object. TraceContext is a sealed class with only one constructor: that takes an HttpContext object. Moq is unable to mock either TraceContext or HttpContext. Can I do anything here to test this code with Moq?
Or will I need to factor this code out and stop referring to HttpContextBase.Trace?
I sort of hate answers that say "don't do that" because there might be value in the answer, regardless of the approach, however, here we go:
Don't do that.
Let's assume you have this class:
public class MyCode
{
public void Do()
{
HttpContext.Current.Trace.WriteLine("WOO!");
}
}
This kind of thing isn't very testable. If you wanted to refactor for testability, you could use more of an "inversion of control" type of method. Here I'll use "dependency injection" (there are other options, like "service location" and "abstract factories", but this is easiest to understand):
public class MyCode
{
private IMyLogger _logger = null;
public MyCode(IMyLogger logger)
{
_logger = logger;
}
public void Do()
{
_logger.TraceWriteLine("WOO!");
}
}
Now you can see that this code is very testable and you don't have to jump through hoops to mock anything.
//Confirms "Do" method calls "TraceWriteLine"
public void Do_Called_CallsTraceWriteLine()
{
//Arrange
var loggerMock = new Mock<IMyLogger>();
loggerMock.Setup(l => l.TraceWriteLine(It.IsAny<string.());
var target = new MyCode(loggerMock.Object);
//Act
target.Do();
//Assert
loggerMock.VerifyAll();
}
Now your implementation of IMyLogger might call out to HttpContext, but it keeps your target class testable.
public DefaultLogger : IMyLogger
{
public void TraceWriteLine(string message)
{
HttpContext.Current.Trace.WriteLine(message);
}
}
To implement such a thing, many people choose to use an Inversion of Control container. You don't have to do this, but it makes things a little simpler and doesn't decrease maintainability as you add more dependencies. You can imagine if you had an interface for each part of the .NET framework that was untestable, your "new MyCode" constructor calls would start to get quite long. IoC containers help you avoid this.
Popular IoC containers for .NET:
Ninject
Unity
MEF (builtin to .NET 4.0)
Autofac
Castle Windsor
StructureMap
Your post is tagged "ASP.NET". Hopefully you are using MVC. If so, it has new support for dependency injection, examples here:
http://weblogs.asp.net/shijuvarghese/archive/2011/01/21/dependency-injection-in-asp-net-mvc-3-using-dependencyresolver-and-controlleractivator.aspx
Hopefully this helps. Sorry it doesn't directly answer your question.