When I execute my test case, it fails for path within my machine which doesn't exist and I am getting below error:
System.IO.DirectoryNotFoundException: Could not find a part of the
path 'C:\Data1'.
Do I need some kind of fake/mock here to pass the test case or do we have other way to do this?
Class
public class DemoCls
{
public void Execute()
{
string dataFolder = #"C:\\Data1";
foreach (string X in Directory.EnumerateFiles(dataFolder, "test" + "*.xml"))
{
}
}
}
Test Case
[TestClass()]
public class DemoClsTests
{
[TestMethod()]
public void ExecuteTest()
{
var X = new DemoCls();
X.Execute();
}
}
Class should be refactored to remove tight coupling to implementation concerns that make it difficult to test.
//...Creat an abstraction that provides the desired behavior as a contract
public interface IDirectoryService {
IEnumerable<string> EnumerateFiles(string path, string searchPattern);
}
A fake/mock can be created for when testing to avoid pitfalls associated with testing IO code in isolation.
A mocking framework could have been used for stubbing the dependencies, but for this example using a simple
public class FakeDIrectoryService : IDirectoryService {
IEnumerable<string> files;
public FakeDIrectoryService(IEnumerable<string> files) {
this.files = files;
}
public IEnumerable<string> EnumerateFiles(string path, string searchPattern = null) {
return files;
}
}
Class needs to be refactored now to follow Explicit Dependencies Principle via constructor and method injection.
public class DemoCls {
IDirectoryService directory;
public DemoCls(IDirectoryService directory) {
this.directory = directory;
}
public void Execute(string dataFolder) {
foreach (var x in directory.EnumerateFiles(dataFolder, "test*.xml")) {
//...
}
}
}
Test can now be properly exercised in isolation.
[TestClass()]
public class DemoClsTests {
[TestMethod()]
public void ExecuteTest() {
//Arrange
var fakePath = "C:/temp";
var fakeFiles = new[] {
#"C:\\temp\\testfakefilename1.txt",
#"C:\\temp\\testfakefilename2.txt",
#"C:\\temp\\testfakefilename3.txt"
};
var service = new FakeDIrectoryService(fakeFiles);
var sut = new DemoCls(service);
//Act
sut.Execute(fakePath);
//Assert
//perform your assertions
}
}
Finally for production code the real implementation of the file service can wrap any source, be it disk or remote service.
For example
public class FileService : IDirectoryService {
public IEnumerable<string> EnumerateFiles(string path, string searchPattern) {
return Directory.EnumerateFiles(path, searchPattern);
}
}
This is just an example of what can be done. There is a lot of room for improvement but this should get things started.
Hardcoded paths are not good to have and I would recommend two options since the class is not static.
1st
public class DemoCls
{
public void Execute(string targetPath)
{
foreach (string X in Directory.EnumerateFiles(targetPath, "test" + "*.xml"))
{
}
}
}
This keeps things more flexible and reusable
2nd
public class DemoCls
{
private string _targetPath;
public DemoCls(string targetPath){
_targetPath = targetPath;
}
public void Execute(string targetPath)
{
foreach (string X in Directory.EnumerateFiles(targetPath, "test" + "*.xml"))
{
}
}
}
This way keeps the Execute method cleaner (less preferred)
Related
Are there any options to pass data from non-static TestCaseSource or ValueSource?
I want to pass some data to tests from an injected dbContext so I can't use static sources.
The following code throws an error:
"The sourceName specified on a ValueSourceAttribute must refer to a non-null static field, property or method."
[Parallelizable(ParallelScope.All)]
[FixtureLifeCycle(LifeCycle.InstancePerTestCase)]
public class MyTests
{
public MyTests()
{
}
public IEnumerable ValueSource
{
get
{
yield return new TestCaseData("test1");
yield return new TestCaseData("test2");
// yield some data from DbContext
}
}
[Test]
public void MyTest([ValueSource(nameof(ValueSource))] string name)
{
Console.WriteLine(name);
}
}
That doesn't work either.
[Parallelizable(ParallelScope.All)]
public class MyTests
{
private static List<TestCaseData> additional = new List<TestCaseData>();
[OneTimeSetUp]
public void OneTimeSetUp()
{
additional.Add(new TestCaseData("test3"));
}
public static IEnumerable<TestCaseData> TestCases
{
get
{
yield return new TestCaseData("test1");
yield return new TestCaseData("test2");
foreach (var testCase in additional)
yield return testCase;
}
}
[Test, TestCaseSource(nameof(TestCases))]
public void MyTest(string name)
{
Console.WriteLine(name);
}
}
No.
However, you can work around the problem by using the [OneTimeSetUp] attribute to populate your static test data from the database. This will perform better, anyway, since you won't need to hit the database for each test.
[Parallelizable(ParallelScope.All)]
public class MyTests
{
private static List<TestCaseData> databaseTests = new List<TestCaseData>();
[OneTimeSetUp]
public void OneTimeSetUp()
{
var dbData = // Run query...
foreach (var item in dbData)
{
databaseTests.Add(TestCaseData(item));
}
}
public static IEnumerable ValueSource
{
get
{
yield return new TestCaseData("test1");
yield return new TestCaseData("test2");
// yield some data from DbContext
foreach (var testCase in databaseTests)
yield return testCase;
}
}
[Test]
public void MyTest([ValueSource(nameof(ValueSource))] string name)
{
Console.WriteLine(name);
}
}
NOTE: It is usually not advisable to use a real database when testing. This means your tests will require a database to be present in the environment that you run them in, instead of having tests that "just work" for whoever runs them. Instead, it is preferable to mock the data that you would ordinarily retrieve from a database so you don't have this extra dependency.
I have a class with a lot of functions in it:
MyClass.cs Methods:
Login
Upload file
Upload Folder
Upload large file
Download
and many more.
the problem is that the class grows and grows, and it's starting to be not comfortable to write the whole methods in the same class.
In one hand I want to invoke the functions like:
var myclass=new MyClass();
myclass.SomeMethod();
but the price is to put all the classes in the same file.
I there any design pattern for this? or any other ideas would be appreciated
What about using dependency inversion?
You can then define your main class such as this
public class MyClass
{
public IUserManagement UserManager { get; set; }
public IFileManagement FileManager { get; set; }
public IFolderManagement FolderManager { get; set; }
public MyClass()
{
}
}
With these interfaces
public interface IUserManagement
{
void Login(string username, string password);
void Logout();
}
public interface IFileManagement
{
void UploadFile(string path);
void UploadLargeFile(string path);
void DownloadFile(string filename, string savePath);
}
public interface IFolderManagement
{
void DownloadFolder(string path);
void UploadFolder(string path);
}
The Bulk of your code then goes into classes which perform a specific task such as this.
public class MyFileManager : IFileManagement
{
public void DownloadFile(string filename, string savePath)
{
//Add code here
}
public void UploadFile(string path)
{
//Add code here
}
public void UploadLargeFile(string path)
{
//Add code here
}
}
public class MyUserManager : IUserManagement
{
public void Login(string username, string password)
{
//Add code here
}
public void Logout()
{
//Add code here
}
}
public class MyFoldermanager : IFolderManagement
{
public void DownloadFolder(string path)
{
//Add code here
}
public void UploadFolder(string path)
{
//Add code here
}
}
You can then create your class and call methods likes this
MyClass myClass = new MyClass()
{
FileManager = new MyFileManager(),
FolderManager = new MyFoldermanager(),
UserManager = new MyUserManager()
};
myClass.FileManager.DownloadFile("myfilename", #"c:\path\to\file.txt");
If you wanted, then you could also add wrappers in your MyClass to hide some of the complexity such as this.
//Add in MyClass
public void UploadFile(string path)
{
this.FileManager.UploadFile(path);
}
//Called like this
myClass.UploadFile(#"c:\path\to\other\file.txt");
This way, you can delegate responsibility for each functional area to a specific class which is easier to manage.
Just extract the code inside the methods of your MyClass to other classes. In MyClass you just call/delegate to the other classes.
This way you can reduce the amount of code in MyClass without reducing its method list.
I am trying to figure out how or if it is possible to do the following with Moq
public class Download
{
private IFoo ifoo;
public Download(IFoo ifoo)
{
this.ifoo = ifoo;
}
public void Download()
{
var files = Directory.GetFiles("filepath"); //<<<===
foreach (var item in files)
{
// do something
}
}
}
In unit test.
// Arrange
var mockFoo = new Mock<IFoo>();
mockFoo.setup( s => s.Bar()).returns(true);
var foo = new Foo(mockFoo.Object);
// Act
foo.Download()
How can I mock the files variable, so the method uses the mock version. Is this even the correct approach? As I am not mocking the class, and rather mocking the dependency how do I go about settings the files variable so it looks at mocked file string[].
You would need to depend on an abstraction to get your files instead of having a hard dependency on System.IO.Directory:
public interface IFileProvider
{
string[] GetFiles(string path);
}
public class PhysicalFileProvider : IFileProvider
{
public string[] GetFiles(string path)
{
return Directory.GetFiles(path);
}
}
You would inject the abstraction in exactly the same way as you're injecting IFoo.
Now you can mock IFileProvider using Moq, creating a mock that returns exactly the strings that you want it to return.
var fileProvider = new Mock<IFileProvider>();
fileProvider.Setup(x => x.GetFiles(It.IsAny<string>()))
.Returns(new[] {"file1.txt", "file2.txt"});
You can also use Microsoft.Extensions.FileProviders.Physical which provides both the file system access and the abstraction.
public class Download
{
private readonly IFoo _foo;
private readonly Microsoft.Extensions.FileProviders.IFileProvider _fileProvider;
public Download(IFoo foo, IFileProvider fileProvider)
{
_foo = foo;
_fileProvider = fileProvider;
}
public void SomethingWithFiles()
{
var files = _fileProvider.GetDirectoryContents("filepath")
.Where(item => !item.IsDirectory);
foreach (var item in files)
{
// something
}
}
}
The concrete implementation would be PhysicalFileProvider.
One more variation. Instead of injecting an interface, inject a delegate:
public delegate string[] GetFilesFunction(string path);
public class Download
{
private readonly IFoo _foo;
private readonly GetFilesFunction _getFiles;
public Download(IFoo foo, GetFilesFunction getFiles)
{
_foo = foo;
_getFiles = getFiles;
}
...
That's even easier to mock. You don't even need Moq.
var subject = new Download(mockedFoo, path => new []{"file1.txt","file2.txt"} );
So I have production code, compiled against production dlls. They access the real architecture of the system.
I'm working on a simulator that will simulate this architecture. All the classes in the simulation are named the same and belong to the same namespaces as the production classes.
People can use my simulation dlls to do a rough draft test of their code.
However, if they call existing production business logic that was compiled against the production classes, it will load the existing production dlls and use the real architecture.
If people want to use my simulation, but call existing business logic, I'd have to use some kind of injection to overwrite the dll that loads the production classes.
Is this possible?
For an example:
I have a dll called Production.dll
In it there is a class like so.
namespace Production
{
public class A { public void Do(); }
}
Now, I have a dll called Simulation.dll with the same class and code.
Someone wrote a program called DoA.exe
public static class Program
{
public static Main()
{
var a = new Production.A();
a.Do();
}
}
I want to make DoA.exe load my simulation dll, but I may not be able to remove Production.dll from its search path. How can I force it to use Simulation.dll instead.
I think I understand better your problem. While I think my original solution is cleaner, this is how to do it "dirty".
Assuming your class schema is like this (simplified):
// assembly: Production.dll (no dependencies)
namespace Production {
public class Test {
public void Do() {
Console.Out.WriteLine("Production");
}
}
}
// assembly: Simulation.dll (no dependencies)
namespace Production {
public class Test {
public void Do() {
Console.Out.WriteLine("Simulation");
}
}
}
// assembly: Usage.dll (dependency on Production.dll)
namespace Usage {
public class TestUsage {
public void Do() {
new Production.Test().Do();
}
}
}
And finally code that will perform the override:
// Console application ConsoleApplication.exe
// dependency on Production.dll, Usage.dll and Simulation.dll
namespace ConsoleApplication {
internal class AssemblyResolver : MarshalByRefObject {
static internal void Register(AppDomain domain) {
var resolver = domain.CreateInstanceFromAndUnwrap(
Assembly.GetExecutingAssembly().Location,
typeof(AssemblyResolver).FullName) as AssemblyResolver;
resolver.RegisterDomain(domain);
}
private void RegisterDomain(AppDomain domain) {
domain.AssemblyResolve += ResolveAssembly;
}
private Assembly ResolveAssembly(object sender, ResolveEventArgs args) {
var assemblyName = new AssemblyName(args.Name);
string name = assemblyName.Name;
// comment out line below and you'll load "Production" instead
if (name == "Production") {
name = "Simulation";
}
var fileNames = new[] { name + ".dll", name + ".exe" };
foreach (string fileName in fileNames) {
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
if (File.Exists(path)) {
return Assembly.Load(File.ReadAllBytes(path));
}
}
return null;
}
}
class Program {
static void Main(string[] args) {
var domain = AppDomain.CreateDomain("Doable", null, new AppDomainSetup {
DisallowApplicationBaseProbing = true
});
AssemblyResolver.Register(domain);
domain.DoCallBack(() => {
// writes out "Simulation"
new Usage.TestUsage().Do();
});
}
}
}
I'm using Dependency Injection to handle problems like this:
Suppose you have interface like
public interface IDoable {
void Do();
}
in Interfaces.dll
and than you have Production.dll with class like:
namespace Production {
internal class Doable : IDoable {
public void Do() { Console.Out.WriteLine("Production"); }
}
public static class Bootstrapper {
static void Init(IServiceLocator locator) {
locator.AddSingleton<IDoable, Doable>();
}
}
}
and then you have Simulation.dll with class like
namespace Simulation {
internal class Doable : IDoable {
public void Do() { Console.Out.WriteLine("Simulation"); }
}
public static class Bootstrapper {
static void Init(IServiceLocator locator) {
locator.AddSingleton<IDoable, Doable>();
}
}
}
Then in your MainAssembly you can reference both, and resolve what implementation you want to use via configuration (naive example below). Except for the configuration line, you don't really have to care from which assembly the IDoable came from - you just use it.
public static Main()
{
Production.Bootstrapper.Init(ServiceLocator.Instance);
// or you can use
// Simulation.Bootstrapper.Init(ServiceLocator.Instance);
IDoable doable = ServiceLocator.Instance.Resolve<IDoable>();
doable.Do();
}
Utility classes (using Microsoft Unity Container from Enterprise Library):
public interface IServiceLocator {
void Add<TFrom, TTo>() where TTo : TFrom;
void BuildUp<T>(T instance);
void BuildUp(Type type, object instance);
void AddSingleton<TFrom, TTo>() where TTo : TFrom;
void AddSingleton<TFrom, TTo>(string name) where TTo : TFrom;
void AddSingleton(Type from, Type to, string name);
void AddInstance<T>(T instance);
T Resolve<T>();
T Resolve<T>(string name);
}
public class ServiceLocator : IServiceLocator {
private IUnityContainer m_Container = new UnityContainer();
public void Add<TFrom, TTo>() where TTo : TFrom {
m_Container.RegisterType<TFrom, TTo>();
}
public void BuildUp<T>(T instance) {
m_Container.BuildUp<T>(instance);
}
public void BuildUp(Type type, object instance) {
m_Container.BuildUp(type, instance);
}
public void AddSingleton<TFrom, TTo>() where TTo : TFrom {
m_Container.RegisterType<TFrom, TTo>(new ContainerControlledLifetimeManager());
}
public void AddSingleton<TFrom, TTo>(string name) where TTo : TFrom {
m_Container.RegisterType<TFrom, TTo>(name, new ContainerControlledLifetimeManager());
}
public void AddSingleton(Type from, Type to, string name) {
m_Container.RegisterType(from, to, name, new ContainerControlledLifetimeManager());
}
public void AddInstance<T>(T instance) {
m_Container.RegisterInstance<T>(instance);
}
public T Resolve<T>() {
return m_Container.Resolve<T>();
}
public T Resolve<T>(string name) {
return m_Container.Resolve<T>(name);
}
private static IServiceLocator s_Instance;
public static IServiceLocator Instance {
get { return s_Instance; }
}
static ServiceLocator() {
var instance = new ServiceLocator();
instance.AddInstance<IServiceLocator>(instance);
s_Instance = instance;
}
}
I have some test code that seems to be running out of the correct order.
[TestClass]
public class DirTest {
public DirTest() {
Assert.AreEqual( Directory.Exists( "testpath" ), true );
}
[TestMethod]
public void TestMethod1() {
}
[ClassInitialize]
public static void InitTest( TestContext context ) {
Directory.CreateDirectory( "testpath" );
}
}
It throws an error that the directory does not exist, shouldn't ClassInitialize run before the class constructor is called or is there something I need to do that is missing. If that is not the case is there a test case other then AssemblyInitialize that can be included in the test that is called prior to the class being constructed?
-- Edit
The real issue is here, the top is a simplification.
//RealClass.cs
public class RealClass{
public RealClass( string path ){
this._path = path;
this._InitDirectory();
}
protected string _path;
protected void _InitDirectory(){
//Something that requires read from path
File.WriteAllText( this._path + "/realData.data", "some real data that needs to be created by the class" );
}
}
//DirTest.cs
[TestClass]
public class DirTest : RealClass {
public DirTest() : base( "testpath" ) {}
[TestMethod]
public void TestMethod1() {
}
[ClassInitialize]
public static void InitTest( TestContext context ) {
Directory.CreateDirectory( "testpath" );
}
}
The unit test will fail because the directory where the path is required will die before the "ClassInitialize" method is called to create the mock directory required.
-- Edit
I have come up with a work around for this, though I would still like to know if there is another way to achieve the desired result without adding more classes, and without removing the functionality of the test. I have setup a "AssemblyInitialize" to a class that just contains that static method, and told that method to fire the static methods for "ClassInitialize". It of course fires before any constructors. Though the root of the issue is still unresolved as it is not self contained but dependent on a class function to call the class setup.
You're trying to use the approach of deriving your [TestClass] from your SUT class in order to access protected methods.
Firstly: is what you're doing really necessary? In the code you posted, there are no tests that explicitly try to access a protected member of the SUT. So, it's possible that you're making things more difficult than they need to be.
Now, if you do actually need to test a protected member in this SUT class, then have you considered creating an class that inherits from the SUT class - a class that isn't the [TestClass]? For example:
//RealClass.cs
public class RealClass{
public RealClass( string path ){
this._path = path;
this._InitDirectory();
}
protected string _path;
protected void _InitDirectory(){
//Something that requires read from path
File.WriteAllText( this._path + "/realData.data", "some real data that needs to be created by the class" );
}
}
// TestableRealClass.cs - Only used by the unit test
public class TestableRealClass: RealClass {
public TestableRealClass(string path) : base(path) { }
public string Path {
get {
return _path;
}
}
public InitDirectory() {
_InitDirectory();
}
}
//DirTest.cs
[TestClass]
public class DirTest {
[TestMethod]
public void TestMethod1() {
var testPath = #"C:\SomePath";
if (!Directory.Exists( testPath )) {
Directory.CreateDirectory( testPath );
}
var sut = new TestableRealClass(testPath);
AssertThatTheFileContainsExpectedStuff(testPath);
}
[TestMethod]
public void TestAProtectedMember() {
var testPath = #"C:\SomePath";
if (!Directory.Exists( testPath )) {
Directory.CreateDirectory( testPath );
}
var sut = new TestableRealClass(testPath);
Assert.AreEqual(testPath, sut.Path);
}
private void AssertThatTheFileContainsExpectedStuff(string path) {
// Do the assertion...
}
}
This way you don't have to worry about the order in which the text fixture will initialize, and your tests become considerably easier to understand.
update your code as follows:
[TestClass]
public class DirTest {
public DirTest() { }
[TestMethod]
public void TestMethod1() {
}
[ClassInitialize]
public static void InitTest( TestContext context ) {
if (!Directory.Exists( "testpath" )) {
Directory.CreateDirectory( "testpath" );
}
}
}