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
Related
I'm trying to add tests to a webforms project. There's a static method to grab lines from resource files. One of the classes I'm trying to test, relies on grabbing text from the resource file.
public static class MyStaticClass {
public static string getText(String name)
{
String s = HttpContext.GetGlobalResourceObject("MyResources", name).ToString();
return s;
}
}
public class ClassUnderTest
{
// returns: "Hey it's my text"
private string _eg = MyStaticClass.getText("label_in_resources.resx_file")
}
class UnitTests
{
[Test]
public void TestMyClass()
{
ClassUnderTest _cut = new ClassUnderTest();
// errors out because ClassUnderTest utilizes getText
// which requires HttpContext.GetGlobalResourceObject
// ... other stuff
}
}
Note: these are simplistic examples.
The issue is that I get a Test Failed with the message:
Message: System.NullReferenceException : Object reference not set to an instance of an object.
With my sleuthing, I've determined that this is because HttpContext is null during these tests.
I've looked at quite a few SO posts on mocking HttpContext but I don't think that I fully understand what exactly they're doing as they're typically dealing with MVC and not Webforms. Still most of them use HttpContextBase and/or HttpContextWrapper but again, I'm not sure how to implement them.
Also - I'm not directly testing the getText method. I know it works. I'm testing a class that uses it. Will mocking the HttpContext even help in this situation?
I do realize that this is sort of a hybrid of a unit test / integration test, so if this isn't the best way, I'm all ears... or.. eyes rather.
Edit
For now, I modified my getText method to return the key (name) if the result of HttpContext.GetGlobalResourceObject is null. Then I updated my tests to expect the key instead of the value. It's not ideal, but it works and allows me to continue. If there's a better way, please let me know.
public static class MyStaticClass {
public static string getText(String name)
{
String s = HttpContext.GetGlobalResourceObject("MyResources", name);
return s != null ? s.ToString() : name;
}
}
Original answer with Fakes (see below for dealing with removing static)
So there's one caveat that I completely forgot about until I just tried to do this. I am pretty sure Fakes still requires Enterprise version of VS. I don't know if there's a way to get it to work with NUnit, but when you aren't able to change the code sometimes you have to just deal with it.
Here's an example of Shimming your static method. You don't need to worry about HttpContext (yet) since you aren't using it directly. Instead you can Shim your getText(string) method.
Actual Business Project
namespace FakesExample
{
public class MyStaticClass
{
public static string GetText(string name)
{
throw new NullReferenceException();
}
}
}
Your Unit Test Project
using System;
using Microsoft.QualityTools.Testing.Fakes;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace FakesExampleTests
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
using (ShimsContext.Create())
{
FakesExample.Fakes.ShimMyStaticClass.GetTextString = (s) =>
{
return "Go away null reference";
};
Console.WriteLine(FakesExample.MyStaticClass.GetText("foo"));
}
}
}
}
I actually ran this so I know it works. What happens is that even though GetText will always throw a NullReferenceException when called, our Shim of it returns our own custom message.
You may have to make a Visual Studio Test Project.
In your Unit Test project, right-click your reference and say "Add Fakes". It will generate all of the Shims and Stubs for your assembly.
Process of removing the static
The best solution is to actually work towards removing the static. You've already hit one major reason to not use them.
Here's how I would go about removing the static and removing the dependency on HttpContext
public interface IResourceRepository
{
string Get(string name);
}
public class HttpContextResourceRepository : IResourceRepository
{
public string Get(string name)
{
return HttpContext.GetGlobalResourceObject("MyResources", name).ToString();
}
}
public class MyFormerStaticClass
{
IResourceRepository _resourceRepository;
public MyFormerStaticClass(IResourceRepository resourceRepository)
{
_resourceRepository = resourceRepository;
}
public string GetText(string name)
{
return _resourceRepository.Get(name);
}
}
I would then leverage Dependency Injection to handle the creation of my HttpContextResourceRepository and MyStaticClass (which should probably also be interfaced) in the actual business code.
For the unit test, I would mock the implementation
[TestFixture]
public class UnitTest1
{
[Test]
public void TestMethod1()
{
var repoMock = new Mock<IResourceRepository>();
repoMock.Setup(repository => repository.Get("foo")).Returns("My Resource Value");
var formerStatic = new MyFormerStaticClass(repoMock.Object);
Console.WriteLine(formerStatic.GetText("foo"));
}
}
Going this route, you can create any number of IResourceRepository implementations and swap them whenever you want.
I have a project named A that has a class named ClassA.
ClassA has a method named ReadBlock() which creates a CloudBlockBlob object and calls one of its methods.
CloudBlockBlob is a class which is located in Microsoft.WindowsAzure.Storage.Blob namespace which is in Microsoft.WindowsAzure.Storage.dll.
My project A has a unit testing project named A.Tests.
Now, I want to test method ReadBlock(). To test it, I need to mock the CloudBlockBlob object and intercept the calls to its methods, return custom values and verify that the methods were called.
How can I mock an object that is fully created inside a method?
Can I somehow change project A's dll reference and reference it to a mock dll that creates a mock object instead the real one?
Can I override project A's call for classes inside the Microsoft.WindowsAzure.Storage.Blob with an implementation of my own in A.Tests class?
UPDATE:
The question is whether I can do this without modifying project A's code.
Thanks!
Without modifing class A code you won't be able to UT the ReadBlock method using Moq. You'll be able to UT this method using code weaving tools (MsFakes, Typemock Isolator, etc...)
For example(MsFakes):
[TestMethod]
public void TestMethod1()
{
using (ShimsContext.Create())
{
ShimCloudBlockBlob.AllInstances.<the method you want to override> = (<the method arguments>) => {};
}
}
Inside the using scope you'll be able to override any method CloudBlockBlob has, through the property AllInstances.
In the next section I'm going to discuss all the other options you have...
Option 1:
public class A
{
private IBlockBlob _blockBlob;
public A(IBlockBlob blockBlob)
{
_blockBlob = blockBlob;
}
public void ReadBlock()
{
_blockBlob.DoSomething();
}
}
Since you create a new instance each time call ReadBlock(your method's current behavior) you better inject a factory instead of wrapper and DoSomething should be create; Option 2:
public class A
{
private readonly IFactoryBlockBlob _blobFctory;
public A(IFactoryBlockBlob blobFctory)
{
_blobFctory = blobFctory;
}
public void ReadBlock()
{
var blob = _blobFctory.Create();
}
}
However, based on your question and your comments it seems that your class 'has a dependency' instead of 'needs a dependency'.
(Mark Siemens wrote a great book about DI, this chart was taken from his book)
With this new piece of information your method should be something like; Option 3:
public class A
{
public void ReadBlock(ICloudBlob blob)
{
}
}
But you don't want to change the signature of the method:
public class A
{
public void ReadBlock()
{
ReadBlock(new CloudBlockBlob(<the params bla bla...>));
}
internal void ReadBlock(ICloudBlob blob)
{
}
}
Add InternalsVisibleToAttribute, then verify the behavior of the internal method.
By reading between the lines, it feels to me that your class is a kind of "legacy code" meaning that it can do the job, won't change, and verifying its behavior might be a waste of time. In the past I've posted a chart (in this answer) which may help you to decide the way to handle this case.
Its probably best to create a very simple mockable wrapper for CloudBlockBlob to improve your code's testability and inject it using dependency inversion.
Right now you probably have something like:
public class A
{
public void ReadBlock()
{
var blockBlob = new CloudBlockBlob();
blockBlob.DoSomething();
}
}
Instead, inject your wrapper into A so that the dependency on CloudBlockBlob is not known to A:
public class A
{
IBlockBlob _blockBlob
public A(IBlockBlob blockBlob)
{
_blockBlob = blockBlob;
}
public void ReadBlock()
{
_blockBlob.DoSomething();
}
}
Disclaimer, I work in Typemock.
You can do it without modifying project A's code using Isolator.
There is a simple example how it can be done:
public class Foo
{
public void ReadBlock()
{
var block = new CloudBlockBlob(new Uri("http://myUrl/%2E%2E/%2E%2E"));
var name = block.Name;
}
}
[TestMethod, Isolated]
public void TestReadBlock()
{
//Arrange
var fakeBlock = Isolate.Fake.AllInstances<CloudBlockBlob>();
Isolate.WhenCalled(() => fakeBlock.Name).WillReturn("Name");
//Act
var foo = new Foo();
foo.ReadBlock();
//Assert
Isolate.Verify.WasCalledWithAnyArguments(() => fakeBlock.Name);
}
Hope it helps!
I have to find info about the currently running UnitTest from a helper class' static method.
The Idea is getting a unique key from each test.
I thought about using TestContext, not sure if it is possible.
Exemple
[TestClass]
public void MyTestClass
{
public TestContext TestContext { get; set; }
[TestMethod]
public void MyTestMethod()
{
TestContext.Properties.Add("MyKey", Guid.NewGuid());
//Continue....
}
}
public static class Foo
{
public static Something GetSomething()
{
//Get the guid from test context.
//Return something base on this key
}
}
We are currently storing this key on the thread with Thread.SetData, but it is problematic if the tested code spawn multiple thread. For each thread I need to get the same key for a given unit test.
Foo.GetSomething() is not called from the unittest itself. The code calling it is a mock injected by Unity.
Edit
I'll explain the context a little bit, because it seems to be confusing.
The object created via unity is entity framework's context. When running unit tests, the context get its data in a structure that is created by Foo.GetSomething. Let's call it DataPersistance.
DataPersistance cannot be a singleton, because unit tests would impact each others.
We currently have one instance of DataPersistance per thread, witch is nice as long as the tested code is single threaded.
I want one instance of DataPersistance per unit test. If a could get an unique guid per test, I could resolve the instance for this test.
public static class Foo
{
public static Something GetSomething(Guid guid)
{
//Return something base on this key
return new Something();
}
}
Test:
[TestClass]
public void MyTestClass
{
public TestContext TestContext { get; set; }
[TestMethod]
public void MyTestMethod()
{
Guid guid = ...;
Something something = Foo.GetSomething(guid);
}
}
I have unit test project called “MyClassTest” in TeamTest. This project has three TestMethods. Each method needs its own test initialization steps. But when I apply TestInitializeAttribute to three initialization methods, it says the attribute should not be used more than once. Then what should be the attribute to be used to initialize each test method in Visual Studio Team Test?
Reference:
VS Team Test: .Net Unit Testing with Excel as Data Source: Adapter Failed
How to create Startup and Cleanup script for Visual Studio Test Project?
VS 2010 Load Tests Results with custom counters
How to log unit test entry and leave in MSTest
Can a unit test project load the target application's app.config file?
According to MSDN the TestInitializeAttribute:
cannot be used more than once (AllowMultiple = false), and
cannot be inherited to create your own TestInitializeAttribute.
So, my suggestion is to create the Test Initialize Methods without the TestInitialize attribute. Then in the unique TestInitialize method check which is the current executed TestMethod and call the appropriate initialize method:
[TestClass]
public class UnitTest
{
public TestContext TestContext { get; set; }
[TestInitialize]
public void Initialize()
{
switch (TestContext.TestName)
{
case "TestMethod1":
this.IntializeTestMethod1();
break;
case "TestMethod2":
this.IntializeTestMethod2();
break;
default:
break;
}
}
[TestMethod]
public void TestMethod1()
{
}
[TestMethod]
public void TestMethod2()
{
}
public void IntializeTestMethod1()
{
//Initialize Test Method 1
}
public void IntializeTestMethod2()
{
//Initialize Test Method 2
}
}
If you have three test methods, and each method has its own initialization steps, then why are you moving initialization to method which will run before every test? Only benefit I see, is that nice switch block, which adds some lines to your source file. But it gives you drawback - looking on any of these test methods, you can't really tell in which context method will be executed. So, I use initialization method to setup only basic context, which is really used by all tests in fixture.
Just move context creation to arrange part of each method.
If you have several methods, which use common context, then just extract method, which will setup context for them, and call it at the arrange part. You also can split each context setup to several steps and reuse those steps (like it done in Given-When-Then tools like Specflow).
And, of course, creating different fixtures also option.
It's a bit of an old post, but I came up with the following which seems to work OK:
First, define an attribute class:
[AttributeUsage(AttributeTargets.Method, Inherited = true)]
public class InitialiseWithAttribute : Attribute
{
public string Id { get; private set; }
public InitialiseWithAttribute(string id)
{
Id = id;
}
}
then define an extension method in some convenient utilities class:
public static bool IsInitialisedWith(this string testName, string value)
{
bool result = false;
Type testClassType = new StackFrame(1).GetMethod().DeclaringType;
MethodInfo methodInfo = testClassType.GetMethod(testName);
if (methodInfo != null)
{
InitialiseWithAttribute initialiseWithAttribute =
methodInfo.GetCustomAttribute<InitialiseWithAttribute>(true);
if (initialiseWithAttribute != null)
{
result = initialiseWithAttribute.Id == value;
}
}
return result;
}
Now write your tests, thus:
public TestContext TestContext {get; set;}
[TestInitialize]
public void TestInitialise()
{
if (TestContext.TestName.IsInitalisedWith("DoSomethingSpecial")
{
// ... Do something special
}
else
{
// ... Do something normal
}
}
[TestMethod]
[InitialiseWith("DoSomethingSpecial")]
public void MySpecialTest()
{
// The test
}
If they need three seperate inits; then they should probably be in three separate fixtures each with their own init!
At my job we pass in an argument to TestInitialize method to determine how we want initialization to work.
public partial class CommonActions
{
public void TestInitialize(bool adminTest)
{
try
{
if (adminTest)
{
//do stuff
}
We then have a standard initialization in class definition, which defaults to false.
[TestClass]
public class ProjectTestBase : FrameworkTestBase
{
public CommonActions common { get; set; } = new CommonActions();
[TestInitialize]
public void TestInitialize() => common.TestInitialize(false);
Then in the Test cases themselves you can override the TestInitialize for any test you want.
[TestClass]
public class SetReportsInAdmin : ProjectTestBase
{
[TestInitialize]
public new void TestInitialize() => common.TestInitialize(true);
We use a Boolean to tell if Admin test, which needs to have extra overhead for setup. Take this and apply whatever variables you want in a way the gives you multiple initialization through the use of one method.
I have an immutable class with some private fields that are set during the constructor execution. I want to unit test this constructor but I'm not sure the "best practice" in this case.
Simple Example
This class is defined in Assembly1:
public class Class2Test
{
private readonly string _StringProperty;
public Class2Test()
{
_StringProperty = ConfigurationManager.AppSettings["stringProperty"];
}
}
This class is defined in Assembly2:
[TestClass]
public class TestClass
{
[TestMethod]
public void Class2Test_Default_Constructor()
{
Class2Test x = new Class2Test();
//what do I assert to validate that the field was set properly?
}
}
EDIT 1: I have answered this question with a potential solution but I'm not sure if it's the "right way to go". So if you think you have a better idea please post it.
This example isn't really worth testing, but assume the constructor has some more complex logic. Is the best approach to avoid testing the constructor and to just assume it works if all the tests for the methods on the class work?
EDIT 2: Looks like I made the sample a little to simple. I have updated it with a more reasonable situation.
Nothing, unless you are using that field. You don't want over-specification via tests. In other words, there is no need to test that the assignment operator works.
If you are using that field in a method or something, call that method and assert on that.
Edit:
assume the constructor has some more complex logic
You shouldn't be performing any logic in constructors.
Edit 2:
public Class2Test()
{
_StringProperty = ConfigurationManager.AppSettings["stringProperty"];
}
Don't do that! =) Your simple unit test has now become an integration test because it depends on the successful operation of more than one class. Write a class that handles configuration values. WebConfigSettingsReader could be the name, and it should encapsulate the ConfigurationManager.AppSettings call. Pass an instance of that SettingsReader class into the constructor of Class2Test. Then, in your unit test, you can mock your WebConfigSettingsReader and stub out a response to any calls you might make to it.
I have properly enabled [InternalsVisibleTo] on Assembly1 (code) so that there is a trust relationship with Assembly2 (tests).
public class Class2Test
{
private readonly string _StringProperty;
internal string StringProperty { get { return _StringProperty; } }
public Class2Test(string stringProperty)
{
_StringProperty = stringProperty;
}
}
Which allows me to assert this:
Assert.AreEqual(x.StringProperty, "something");
The only thing I don't really like about this is that it's not clear (without a comment) when you are just looking at Class2Test what the purpose of the internal property is.
Additional thoughts would be greatly appreciated.
In your edit, you now have a dependancy on ConfigurationManager that is hard to test.
One suggestion is to extract an interface to it and then make the Class2Test ctor take an IConfigManager instance as a parameter. Now you can use a fake/mock object to set up its state, such that any methods that rely on Configuration can be tested to see if they utilize the correct values...
public interface IConfigManager
{
string FooSetting { get; set; }
}
public class Class2Test
{
private IConfigManager _config;
public Class2Test(IConfigManager configManager)
{
_config = configManager;
}
public void methodToTest()
{
//do something important with ConfigManager.FooSetting
var important = _config.FooSetting;
return important;
}
}
[TestClass]
public class When_doing_something_important
{
[TestMethod]
public void Should_use_configuration_values()
{
IConfigManager fake = new FakeConfigurationManager();
//setup state
fake.FooSetting = "foo";
var sut = new Class2Test(fake);
Assert.AreEqual("foo", sut.methodToTest());
}
}