how to skip constructor call from unit test? - c#

I am executing unit test for one of class method "Execute", but don't want to execute class constructor code.
Is there any way to skip constructor code call from the unit test execution?
Class Code,
public class DemoCls
{
public DemoCls()
{
string ConfigFolderPath = Path.Combine(Environment.CurrentDirectory, #"\Config");
//string dataFolder = #"C:\Data1";
foreach (string X in Directory.EnumerateFiles(ConfigFolderPath, "test" + "*.xml"))
{
}
}
public void Execute()
{
}
}
Unit Test Code,
[TestClass()]
public class DemoClsTests
{
[TestMethod()]
public void ExecuteTest()
{
var X = new DemoCls();
X.Execute();
}
}

Rewrite the class, one of two ways:
Pass the information into the constructor using an interface (which can be mocked in unit-tests)
public interface IConfigFiles
{
List<string> Files { get; set; }
}
public DemoCls(IConfigFiles files)
{
}
Remove configuration code from the constructor, and put it in a different function instead.
public DemoCls()
{
// does nothing
}
public void Setup()
{
string ConfigFolderPath = Path.Combine(Environment.CurrentDirectory, #"\Config");
//...
}
Interfaces are better for unit-testing.

"Is there any way to skip constructor code call from the unit test execution?"
The answer is: No (for instance methods)

You can use a unit testing frameworks that allows you to mock concrete classes in order to fake a class without an interface, for example i'm using Typemock Isolator and with that i can mock almost any class and decide what is happening with all the class's members and its constructor.
here is a test for the class that you had in your question:
[TestMethod,Isolated]
public void TestMethod()
{
var fake = Isolate.Fake.Instance<DemoCls>(Members.CallOriginal, ConstructorWillBe.Ignored);
fake.Execute();
Isolate.Verify.WasCalledWithAnyArguments(() => fake.Execute());
}

You could wrap you ctor code in the "if" preprocessor directive and execute it conditionally, only during a non-test run.
#define DEBUG
// ...
#if DEBUG
Console.WriteLine("Debug version");
#endif
See
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/preprocessor-directives/preprocessor-if

Related

Moq tell if function was called [duplicate]

I have a base class:
public abstract class MyBaseClass
{
protected virtual void Method1()
{
}
}
and a derived class:
public class MyDerivedClass : MyBaseClass
{
public void Method2()
{
base.Method1();
}
}
I want to write a unit test for Method2 to verify that it calls Method1 on the base class. I'm using Moq as my mocking library. Is this possible?
I came across a related SO link:
Mocking a base class method call with Moq
in which the 2nd answer suggests it can be achieved by setting CallBase property to true on the mock object. However it's not clear how this would enable the call to the base class method (Method1 in the above example) to be verified.
Appreciate any assistance with this.
Unit tests should verify behavior, not implementation. There are several reasons for this:
The results are the goal, not how you get the results
Testing results allows you to improve the implementation without re-writing your tests
Implementations are harder to mock
You might be able to put in hooks or create mocks that verify that the base method was called, but do you really care how the answer was achieved, or do you care that the answer is right?
If the particular implementation you require has side effects that you can verify, then that is what you should be validating.
Mocking the base class from the perspective of the derived class is not possible. In your simple example, I would suggest one of the two options.
Option 1: In the event that MyDerivedClass really shouldn't care what MyBaseClass is up to, then use dependency injection! Yay abstraction!
public class MyClass
{
private readonly IUsedToBeBaseClass myDependency;
public MyClass(IUsedToBeBaseClass myDependency){
_myDependency = myDependency;
}
public void Method2()
{
_myDependency.Method1();
}
}
Elsewhere in test land...
[TestClass]
public class TestMyDependency {
[TestMethod]
public void TestThatMyDependencyIsCalled() {
var dependency = new Mock<IUsedToBeBaseClass>();
var unitUnderTest = new MyClass(dependency.Object);
var unitUnderTest.Method2();
dependency.Verify(x => x.Method1(), Times.Once);
}
}
Option 2: In the event that MyDerivedClass NEEDS to know what MyBaseClass is doing, then test that MyBaseClass is doing the right thing.
In alternative test land...
[TestClass]
public class TestMyDependency {
[TestMethod]
public void TestThatMyDependencyIsCalled() {
var unitUnderTest = new MyDerivedClass();
var unitUnderTest.Method2();
/* verify base class behavior #1 inside Method1() */
/* verify base class behavior #2 inside Method1() */
/* ... */
}
}
What you're describing is not a test of your code, but a test of the behavior of the language. That's fine, because it's a good way to ensure that the language behaves the way we think it does. I used to write lots of little console apps when I was learning. I wish I'd known about unit testing then because it's a better way to go about it.
But once you've tested it and confirmed that the language behaves the way you expect, I wouldn't keep writing tests for that. You can just test the behavior of your code.
Here's a real simple example:
public class TheBaseClass
{
public readonly List<string> Output = new List<string>();
public virtual void WriteToOutput()
{
Output.Add("TheBaseClass");
}
}
public class TheDerivedClass : TheBaseClass
{
public override void WriteToOutput()
{
Output.Add("TheDerivedClass");
base.WriteToOutput();
}
}
Unit test
[TestMethod]
public void EnsureDerivedClassCallsBaseClass()
{
var testSubject = new TheDerivedClass();
testSubject.WriteToOutput();
Assert.IsTrue(testSubject.Output.Contains("TheBaseClass"));
}

I am trying to write Unit Test in C# for static methods

I am learning unit test for c# web application. I am stuck in above mention scenario. I am not sure if I am doing it in correct way. I have FakePath class for unit test. How do I write unit test for static method,Abc.log(), in MSTest?
public class Abc
{
public static void log(string msg)
{
//Read on Write on path;
string path = getPath(new ServerPath());
}
public static string getPath(IServerPath path)
{
return path.MapPath("file.txt");
}
}
interface IServerPath()
{
string MapPath(string file);
}
class ServerPath : IServerPath
{
string MapPath(string file)
{
return HttpContext.Current.Server.MapPath(file);
}
}
class FakeServerPath : IServerPath
{
string MapPath(string file)
{
return #"C:\"+file;
}
}
You are trying to test a void method, so one of your options of asserting this method is to verify if the method is called:
string expectedStr = "c:\file.txt";
[TestMethod]
public void FakeServerPath_VerifyMapPathWasCalled()
{
var fakeServerPath = Isolate.Fake.NextInstance<ServerPath>();
Isolate.WhenCalled(() => fakeServerPath.MapPath("")).WillReturn(expectedStr);
Abc.log("");
Isolate.Verify.WasCalledWithExactArguments(() => fakeServerPath.MapPath("file.txt"));
}
Another option is to test the return value of the getPath(IServerPath path) method, by modifying the return value of ServerPath's MapPath(string file) method to return a wanted value, and to assert if the return value is as expected.
string expectedStr = "c:\file.txt";
[TestMethod]
public void ModifyReturnValueFromMapPath_IsEqualToExpactedStr()
{
var fakeServerPath = Isolate.Fake.NextInstance<ServerPath>();
Isolate.WhenCalled(() => fakeServerPath.MapPath("")).WillReturn(expectedStr);
var result = Abc.getPath(fakeServerPath);
Assert.AreEqual(expectedStr, result);
}
Notice that by using TypeMock Isolator you will be able to fake the future instance of "ServerPath" without changing your original code.
And if necessary TypeMock is also able to mock HttpContext class as so:
string expectedStr = "c:\file.txt";
[TestMethod]
public void ModifyReturnValueFromHttpContext_IsEqualToExpactedStr()
{
var serverPath = new ServerPath();
Isolate.WhenCalled(() => HttpContext.Current.Server.MapPath("")).WillReturn(expectedStr);
var result = Abc.getPath(serverPath);
Assert.AreEqual(expectedStr, result);
}
Testing statics in itself is easy, just call them and assert on the results (the actual problem is testing code that uses statics, as they can't be mocked out). Testing in this particular case is complicated by a different thing.
The real problem of the Log method is that ti creates a ServerPath instance by itself, which precludes any chance of Dependency Injection (on the contrary, the GetPath method is totally friendly to testing, as it takes an interface as a parameter).
I would introduce a refactoring on the Abc class to enable better testing on it. I would modify it as such:
public static class Logger
{
public static void Log(IServerPath path, string msg)
{
//add parameter checking here
string path = path.MapPath("file.txt");
//actual log goes here
}
}
Note that now the test would be responsible to create the IServerPath instance, which can then use to inject the mock
In a case like this you need to expose a way to set the dependency. Currently you are using a new ServerPath() directly in the method which makes it difficult to inject your FakeServerPath for testing.
You can modify Abc
public class Abc
{
static Abc() { ServerPath = new ServerPath(); }
public static IServerPath ServerPath { get; set; }
public static void log(string msg) {
//Read on Write on path;
string path = getPath(ServerPath);
}
public static string getPath(IServerPath path) {
return path.MapPath("file.txt");
}
}
And a test could look like this
[TestMethod]
public void Abc_log_Test() {
//Arrange
string filename = "fakeFile.txt";
string expected = #"C:\" + filename;
var mockServerPath = new Mock<IServerPath>();
mockServerPath
.Setup(m => m.MapPath(filename))
.Returns(expected)
.Verifiable();
Abc.ServerPath = mockServerPath.Object;
var message = "Hello world";
//Act
Abc.log(message);
//Assert
mockServerPath.Verify();
}
Note I used Moq to mock up the server path
Here's a simple approach using dependency injection.
public class FileLogger
{
private readonly string _filePath;
public FileLogger(string filePath)
{
_filePath = filePath;
}
public void Log(string msg)
{
//write to the log
}
}
Now your logging class has a single responsibility - writing to the file. It is not responsible for figuring out which file to write to. It expects to have that value injected into it.
Also, I avoided using a static method. If the method is static then a similar problem occurs again: How do you test classes that depend on the logging class?
By making it non-static you can repeat the same pattern - mock the logger so that you can test classes that depend on it.
public interface ILogger
{
void Log(string msg);
}
Then your logging class can implement the interface and you can inject that interface (instead of a concrete class) into classes that might need to write to a log.
Here's a post which demonstrates injecting a logger into a class. There are often better ways to accomplish the same purpose (like using an interceptor) but at least it prevents your code from having dependencies everywhere on some concrete class.

Is it correct to use Assert.Fail inside methods call by TestMethods

I'm planning to use Assert.Fail in this way in my unit testing.
Inside a private helper method inside the Test class (IsFileExist)
Inside the methods of a helper class (LoadData)
So is this ok? or this is out of the unit test framework usage?
If I did like this when the Assert.Fail execute does it unwind the whole stack for the test method or just only unwind the stack for that particular method?
Helper class
public class DataLoader
{
public void LoadData(string file)
{
if (Util.readfile(file)) {
Assert.Fail("Unable to read the file.");
}
}
}
Test class
[TestClass]
public class testFileData
{
[TestMethod]
public void TestData()
{
string file = "C:\\data.txt";
this.IsFileExist(file);
DataLoader dl = new DataLoader();
dl.LoadData(file);
}
private void IsFileExist(string file)
{
if(!Util.IsFileExist(file)) {
Assert.Fail("File not exist");
}
}
}
The fact that Assert is in the Microsoft.VisualStudio.TestTools.UnitTesting name space should serve as a hint that no, you should not be using it out side of a unit test.
If you want to fail based on a condition in your code, throw an exception.

Do I Stub or Shim a method inside my test method?

I have a method base.ResolveDate() inside my test method that's coming from a base class and its public and virtual. I want to stub/shim this method with my own, so do I stub or shim? Stub or Shim, how would I go about doing it? From my experience with MS Fakes it seems like it would be a Stub because Stub can only influence overridable methods. - ALM 2012
Here is the test method:
public override DateTime ResolveDate(ISeries comparisonSeries, DateTime targetDate)
{
if (comparisonSeries == null)
{
throw new ArgumentNullException("comparisonSeries");
}
switch (comparisonSeries.Key)
{
case SeriesKey.SomeKey1:
case SeriesKey.SomeKey2:
case SeriesKey.SomeKey3:
case SeriesKey.SomeKey4:
case SeriesKey.SomeKey5:
return DateHelper.PreviousOrCurrentQuarterEnd(targetDate);
}
return base.ResolveDate(comparisonSeries, targetDate);
}
Here is the method from the base class I want to Stub/Shim?
public virtual DateTime ResolveDate(ISeries comparisonSeries, DateTime targetDate)
{
if (this.key == comparisonSeries.Key)
return targetDate;
return DateHelper.FindNearestDate(targetDate, comparisonSeries.AsOfDates);
}
To test a derived method in isolation from its base implementation, you need to shim it. Given the following system under test:
namespace ClassLibrary7
{
public class Parent
{
public virtual string Method()
{
return "Parent";
}
}
public class Child : Parent
{
public override string Method()
{
return base.Method() + "Child";
}
}
}
You can write the following test for the Child.Method().
using ClassLibrary7;
using ClassLibrary7.Fakes;
using Microsoft.QualityTools.Testing.Fakes;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Test
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
using (ShimsContext.Create())
{
var child = new Child();
var shim = new ShimParent(child);
shim.Method = () => "Detour";
string result = child.Method();
Assert.IsFalse(result.Contains("Parent"));
Assert.IsTrue(result.Contains("Detour"));
Assert.IsTrue(result.Contains("Child"));
}
}
}
}
Note that the first two Asserts are included only to illustrate how the parent method is detoured. In a real test only asserts for the child method would be needed.
1) First add a reference to the actual dll you want to test example: ABC.Interfaces
2) Then expand your references and on the actual dll that should now be in your references right click and say "Add Fakes Assembly"
Visual studio will process the references and if it was successfull you should see a new reference called ABC.Interfaces.1.0.0.0.Fakes..
You will now be able to see the stub and shims been added to your methods.
Hope this helps!

NUnit executes with alternate constructor

I have a class which has some unit tests, but when I am running tests I would like the class to be created with a different constructor. Something like this:
[TestFixture]
public class MyClass
{
public MyClass() { /* set up for production */ }
[TestFixtureConstructor]
public MyClass() { /* set up for testing */ }
[Test]
public void FirstTest()
{
// assert some values
}
}
Is this even possible?
I have considered using a static factory method for creating the class in production (with a private constructor), and a public constructor for the testing framework.
Does anyone have any other solutions?
You don't do this.
You do not have your tests written inside the class that you use in real code; you write your tests external to the classes. I believe most testing suites have the concept of 'Teardown' and the opposite; to set up the test environment for a given execution.
To give a quick example of silky's correct approach:
public class MyClass
{
// ...
}
// In a different assembly:
[TestFixture]
public class TestMyClass
{
[SetUp]
public void SetUp()
{
_myClass = new MyClass();
}
[Test]
public void FooReturnsTrue()
{
Assert.That(_myClass.Foo(), Is.True);
}
// more tests
private MyClass _myClass;
}
If you really really want this you can take a look at TestFixtureSetUp.
Here's the introduction:
This attribute is used inside a TestFixture to provide a single set of functions that are performed once prior to executing any of the tests in the fixture. A TestFixture can have only one TestFixtureSetUp method. If more than one is defined the TestFixture will compile successfully but its tests will not run.
Example:
namespace NUnit.Tests
{
using System;
using NUnit.Framework;
[TestFixture]
public class SuccessTests
{
[TestFixtureSetUp] public void Init()
{ /* ... */ }
[TestFixtureTearDown] public void Dispose()
{ /* ... */ }
[Test] public void Add()
{ /* ... */ }
}
}
But you should use this with care, or else it defeats the purpose of unit test.

Categories

Resources